From 8f38e3f76eb8e931f6095d7c8953f14585c1a83c Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Fri, 16 Dec 2016 12:47:34 +0100
Subject: [PATCH] template automaton run algorithms

---
 alib2algo/src/automaton/run/Accept.cpp      |  81 +--
 alib2algo/src/automaton/run/Accept.h        | 108 +++-
 alib2algo/src/automaton/run/Occurrences.cpp |  53 +-
 alib2algo/src/automaton/run/Occurrences.h   |  71 ++-
 alib2algo/src/automaton/run/Result.cpp      |  77 +--
 alib2algo/src/automaton/run/Result.h        |  87 ++-
 alib2algo/src/automaton/run/Run.cpp         | 570 ------------------
 alib2algo/src/automaton/run/Run.h           | 606 +++++++++++++++++++-
 alib2algo/src/automaton/run/Translate.cpp   |  15 -
 alib2algo/src/automaton/run/Translate.h     |  20 +-
 10 files changed, 863 insertions(+), 825 deletions(-)
 delete mode 100644 alib2algo/src/automaton/run/Run.cpp

diff --git a/alib2algo/src/automaton/run/Accept.cpp b/alib2algo/src/automaton/run/Accept.cpp
index b6b6d4cf93..9252ee6c4c 100644
--- a/alib2algo/src/automaton/run/Accept.cpp
+++ b/alib2algo/src/automaton/run/Accept.cpp
@@ -6,20 +6,6 @@
  */
 
 #include "Accept.h"
-#include "Run.h"
-#include <automaton/FSM/DFA.h>
-#include <automaton/FSM/NFA.h>
-#include <automaton/TA/DFTA.h>
-#include <automaton/TA/NFTA.h>
-#include <automaton/PDA/InputDrivenDPDA.h>
-#include <automaton/PDA/VisiblyPushdownDPDA.h>
-#include <automaton/PDA/RealTimeHeightDeterministicDPDA.h>
-#include <automaton/PDA/DPDA.h>
-#include <automaton/PDA/NPDTA.h>
-
-#include <deque>
-#include <vector>
-#include <algorithm>
 
 namespace automaton {
 
@@ -37,79 +23,14 @@ bool Accept::accept ( const automaton::Automaton & automaton, const tree::Ranked
 	return dispatch ( automaton.getData ( ), tree );
 }
 
-bool Accept::accept ( const automaton::DFA<> & automaton, const string::LinearString < > & string ) {
-	std::tuple < bool, label::Label, std::set < unsigned > > res = Run::calculateState ( automaton, string );
-
-	return std::get < 0 > ( res ) && automaton.getFinalStates ( ).count ( std::get < 1 > ( res ) );
-}
-
-auto AcceptDFALinearString = Accept::RegistratorWrapper < bool, automaton::DFA<>, string::LinearString < > > ( Accept::accept );
-
-bool Accept::accept ( const automaton::NFA < > & automaton, const string::LinearString < > & string ) {
-	std::tuple < bool, std::set < label::Label >, std::set < unsigned > > res = Run::calculateStates ( automaton, string );
-
-	return std::get < 0 > ( res ) && std::any_of ( std::get < 1 > ( res ).begin ( ), std::get < 1 > ( res ).end ( ), [&] ( const label::Label & state ) {
-				return automaton.getFinalStates ( ).count ( state );
-			} );
-}
-
+auto AcceptDFALinearString = Accept::RegistratorWrapper < bool, automaton::DFA < >, string::LinearString < > > ( Accept::accept );
 auto AcceptNFALinearString = Accept::RegistratorWrapper < bool, automaton::NFA < > , string::LinearString < > > ( Accept::accept );
-
-bool Accept::accept ( const automaton::DFTA < > & automaton, const tree::RankedTree < > & tree ) {
-	std::tuple < bool, label::Label, std::set < unsigned > > res = Run::calculateState ( automaton, tree );
-
-	return std::get < 0 > ( res ) && automaton.getFinalStates ( ).count ( std::get < 1 > ( res ) );
-}
-
 auto AcceptDFTARankedTree = Accept::RegistratorWrapper < bool, automaton::DFTA < >, tree::RankedTree < > > ( Accept::accept );
-
-bool Accept::accept ( const automaton::NFTA < > & automaton, const tree::RankedTree < > & tree ) {
-	std::tuple < bool, std::set < label::Label >, std::set < unsigned > > res = Run::calculateStates ( automaton, tree );
-
-	return std::get < 0 > ( res ) && std::any_of ( std::get < 1 > ( res ).begin ( ), std::get < 1 > ( res ).end ( ), [&] ( const label::Label & state ) {
-				return automaton.getFinalStates ( ).count ( state );
-			} );
-}
-
 auto AcceptNFTARankedTree = Accept::RegistratorWrapper < bool, automaton::NFTA < >, tree::RankedTree < > > ( Accept::accept );
-
-bool Accept::accept ( const automaton::InputDrivenDPDA < > & automaton, const string::LinearString < > & string ) {
-	std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > res = Run::calculateState ( automaton, string );
-
-	return std::get < 0 > ( res ) && ( automaton.getFinalStates ( ).count ( std::get < 1 > ( res ) ) || ( automaton.getFinalStates ( ).size ( ) == 0 && std::get < 3 > ( res ).size ( ) == 0 ) );
-}
-
 auto AcceptInputDrivenDPDALinearString = Accept::RegistratorWrapper < bool, automaton::InputDrivenDPDA < >, string::LinearString < > > ( Accept::accept );
-
-bool Accept::accept ( const automaton::VisiblyPushdownDPDA < > & automaton, const string::LinearString < > & string ) {
-	std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > res = Run::calculateState ( automaton, string );
-
-	return std::get < 0 > ( res ) && automaton.getFinalStates ( ).count ( std::get < 1 > ( res ) );
-}
-
 auto AcceptVisiblyPushdownDPDALinearString = Accept::RegistratorWrapper < bool, automaton::VisiblyPushdownDPDA < >, string::LinearString < > > ( Accept::accept );
-
-bool Accept::accept ( const automaton::RealTimeHeightDeterministicDPDA < > & automaton, const string::LinearString < > & string ) {
-	std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > res = Run::calculateState ( automaton, string );
-
-	return std::get < 0 > ( res ) && automaton.getFinalStates ( ).count ( std::get < 1 > ( res ) );
-}
-
 auto AcceptRealTimeHeightDeterministicDPDALinearString = Accept::RegistratorWrapper < bool, automaton::RealTimeHeightDeterministicDPDA < >, string::LinearString < > > ( Accept::accept );
-
-bool Accept::accept ( const automaton::DPDA < > & automaton, const string::LinearString < > & string ) {
-	std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > res = Run::calculateState ( automaton, string );
-
-	return std::get < 0 > ( res ) && ( automaton.getFinalStates ( ).count ( std::get < 1 > ( res ) ) || ( automaton.getFinalStates ( ).size ( ) == 0 && std::get < 3 > ( res ).size ( ) == 0 ) );
-}
-
 auto AcceptDPDALinearString = Accept::RegistratorWrapper < bool, automaton::DPDA < >, string::LinearString < > > ( Accept::accept );
-
-bool Accept::accept ( const automaton::NPDTA < > & automaton, const string::LinearString < > & string ) {
-	std::tuple < bool, std::set < label::Label >, std::set < std::vector < alphabet::Symbol > > > res = Run::calculateStates ( automaton, string );
-	return std::get<0>(res);
-}
-
 auto AcceptNPDTALinearString = Accept::RegistratorWrapper < bool, automaton::NPDTA < >, string::LinearString < > > ( Accept::accept );
 
 } /* namespace run */
diff --git a/alib2algo/src/automaton/run/Accept.h b/alib2algo/src/automaton/run/Accept.h
index 4da0f7044d..172aec9a3e 100644
--- a/alib2algo/src/automaton/run/Accept.h
+++ b/alib2algo/src/automaton/run/Accept.h
@@ -15,6 +15,21 @@
 #include <string/LinearString.h>
 #include <tree/ranked/RankedTree.h>
 
+#include "Run.h"
+#include <automaton/FSM/DFA.h>
+#include <automaton/FSM/NFA.h>
+#include <automaton/TA/DFTA.h>
+#include <automaton/TA/NFTA.h>
+#include <automaton/PDA/InputDrivenDPDA.h>
+#include <automaton/PDA/VisiblyPushdownDPDA.h>
+#include <automaton/PDA/RealTimeHeightDeterministicDPDA.h>
+#include <automaton/PDA/DPDA.h>
+#include <automaton/PDA/NPDTA.h>
+
+#include <deque>
+#include <vector>
+#include <algorithm>
+
 namespace automaton {
 
 namespace run {
@@ -29,18 +44,93 @@ public:
 	static bool accept ( const automaton::Automaton & automaton, const string::LinearString < > & string );
 	static bool accept ( const automaton::Automaton & automaton, const tree::RankedTree < > & string );
 
-	static bool accept ( const automaton::DFA<> & automaton, const string::LinearString < > & string );
-	static bool accept ( const automaton::NFA < > & automaton, const string::LinearString < > & string );
-	static bool accept ( const automaton::DFTA < > & automaton, const tree::RankedTree < > & tree );
-	static bool accept ( const automaton::NFTA < > & automaton, const tree::RankedTree < > & tree );
-	static bool accept ( const automaton::InputDrivenDPDA < > & automaton, const string::LinearString < > & string );
-	static bool accept ( const automaton::VisiblyPushdownDPDA < > & automaton, const string::LinearString < > & string );
-	static bool accept ( const automaton::RealTimeHeightDeterministicDPDA < > & automaton, const string::LinearString < > & string );
-	static bool accept ( const automaton::DPDA < > & automaton, const string::LinearString < > & string );
-	static bool accept ( const automaton::NPDTA < > & automaton, const string::LinearString < > & string );
+	template < class SymbolType, class StateType >
+	static bool accept ( const automaton::DFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class StateType >
+	static bool accept ( const automaton::NFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class RankType, class StateType >
+	static bool accept ( const automaton::DFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree );
+	template < class SymbolType, class RankType, class StateType >
+	static bool accept ( const automaton::NFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree );
+	template < class SymbolType, class StateType >
+	static bool accept ( const automaton::InputDrivenDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class StateType >
+	static bool accept ( const automaton::VisiblyPushdownDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static bool accept ( const automaton::RealTimeHeightDeterministicDPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static bool accept ( const automaton::DPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static bool accept ( const automaton::NPDTA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string );
 
 };
 
+template < class SymbolType, class StateType >
+bool Accept::accept ( const automaton::DFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	std::tuple < bool, StateType, std::set < unsigned > > res = Run::calculateState ( automaton, string );
+
+	return std::get < 0 > ( res ) && automaton.getFinalStates ( ).count ( std::get < 1 > ( res ) );
+}
+
+template < class SymbolType, class StateType >
+bool Accept::accept ( const automaton::NFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	std::tuple < bool, std::set < StateType >, std::set < unsigned > > res = Run::calculateStates ( automaton, string );
+
+	return std::get < 0 > ( res ) && std::any_of ( std::get < 1 > ( res ).begin ( ), std::get < 1 > ( res ).end ( ), [&] ( const StateType & state ) {
+				return automaton.getFinalStates ( ).count ( state );
+			} );
+}
+
+template < class SymbolType, class RankType, class StateType >
+bool Accept::accept ( const automaton::DFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree ) {
+	std::tuple < bool, StateType, std::set < unsigned > > res = Run::calculateState ( automaton, tree );
+
+	return std::get < 0 > ( res ) && automaton.getFinalStates ( ).count ( std::get < 1 > ( res ) );
+}
+
+template < class SymbolType, class RankType, class StateType >
+bool Accept::accept ( const automaton::NFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree ) {
+	std::tuple < bool, std::set < StateType >, std::set < unsigned > > res = Run::calculateStates ( automaton, tree );
+
+	return std::get < 0 > ( res ) && std::any_of ( std::get < 1 > ( res ).begin ( ), std::get < 1 > ( res ).end ( ), [&] ( const StateType & state ) {
+				return automaton.getFinalStates ( ).count ( state );
+			} );
+}
+
+template < class SymbolType, class StateType >
+bool Accept::accept ( const automaton::InputDrivenDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > res = Run::calculateState ( automaton, string );
+
+	return std::get < 0 > ( res ) && ( automaton.getFinalStates ( ).count ( std::get < 1 > ( res ) ) || ( automaton.getFinalStates ( ).size ( ) == 0 && std::get < 3 > ( res ).size ( ) == 0 ) );
+}
+
+template < class SymbolType, class StateType >
+bool Accept::accept ( const automaton::VisiblyPushdownDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > res = Run::calculateState ( automaton, string );
+
+	return std::get < 0 > ( res ) && automaton.getFinalStates ( ).count ( std::get < 1 > ( res ) );
+}
+
+template < class SymbolType, class EpsilonType, class StateType >
+bool Accept::accept ( const automaton::RealTimeHeightDeterministicDPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > res = Run::calculateState ( automaton, string );
+
+	return std::get < 0 > ( res ) && automaton.getFinalStates ( ).count ( std::get < 1 > ( res ) );
+}
+
+template < class SymbolType, class EpsilonType, class StateType >
+bool Accept::accept ( const automaton::DPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > res = Run::calculateState ( automaton, string );
+
+	return std::get < 0 > ( res ) && ( automaton.getFinalStates ( ).count ( std::get < 1 > ( res ) ) || ( automaton.getFinalStates ( ).size ( ) == 0 && std::get < 3 > ( res ).size ( ) == 0 ) );
+}
+
+template < class SymbolType, class EpsilonType, class StateType >
+bool Accept::accept ( const automaton::NPDTA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	std::tuple < bool, std::set < StateType >, std::set < std::vector < SymbolType > > > res = Run::calculateStates ( automaton, string );
+	return std::get<0>(res);
+}
+
 } /* namespace run */
 
 } /* namespace automaton */
diff --git a/alib2algo/src/automaton/run/Occurrences.cpp b/alib2algo/src/automaton/run/Occurrences.cpp
index a3b38aa6fa..ef7b2f57bd 100644
--- a/alib2algo/src/automaton/run/Occurrences.cpp
+++ b/alib2algo/src/automaton/run/Occurrences.cpp
@@ -6,16 +6,6 @@
  */
 
 #include "Occurrences.h"
-#include "Run.h"
-#include <automaton/FSM/DFA.h>
-#include <automaton/FSM/NFA.h>
-#include <automaton/TA/DFTA.h>
-#include <automaton/PDA/InputDrivenDPDA.h>
-#include <automaton/PDA/VisiblyPushdownDPDA.h>
-#include <automaton/PDA/RealTimeHeightDeterministicDPDA.h>
-#include <automaton/PDA/DPDA.h>
-
-#include <deque>
 
 namespace automaton {
 
@@ -33,52 +23,11 @@ std::set < unsigned > Occurrences::occurrences ( const automaton::Automaton & au
 	return dispatch ( automaton.getData ( ), tree );
 }
 
-std::set < unsigned > Occurrences::occurrences ( const automaton::DFA < > & automaton, const string::LinearString < > & string ) {
-	std::tuple < bool, label::Label, std::set < unsigned > > res = Run::calculateState ( automaton, string );
-
-	return std::get < 2 > ( res );
-}
-
-auto OccurrencesDFALinearString = Occurrences::RegistratorWrapper < std::set < unsigned >, automaton::DFA<>, string::LinearString < > > ( Occurrences::occurrences );
-
-std::set < unsigned > Occurrences::occurrences ( const automaton::DFTA < > & automaton, const tree::RankedTree < > & tree ) {
-	std::tuple < bool, label::Label, std::set < unsigned > > res = Run::calculateState ( automaton, tree );
-
-	return std::get < 2 > ( res );
-}
-
+auto OccurrencesDFALinearString = Occurrences::RegistratorWrapper < std::set < unsigned >, automaton::DFA < >, string::LinearString < > > ( Occurrences::occurrences );
 auto OccurrencesDFTARankedTree = Occurrences::RegistratorWrapper < std::set < unsigned >, automaton::DFTA < >, tree::RankedTree < > > ( Occurrences::occurrences );
-
-std::set < unsigned > Occurrences::occurrences ( const automaton::InputDrivenDPDA < > & automaton, const string::LinearString < > & string ) {
-	std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > res = Run::calculateState ( automaton, string );
-
-	return std::get < 2 > ( res );
-}
-
 auto OccurrencesInputDrivenDPDALinearString = Occurrences::RegistratorWrapper < std::set < unsigned >, automaton::InputDrivenDPDA < >, string::LinearString < > > ( Occurrences::occurrences );
-
-std::set < unsigned > Occurrences::occurrences ( const automaton::VisiblyPushdownDPDA < > & automaton, const string::LinearString < > & string ) {
-	std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > res = Run::calculateState ( automaton, string );
-
-	return std::get < 2 > ( res );
-}
-
 auto OccurrencesVisiblyPushdownDPDALinearString = Occurrences::RegistratorWrapper < std::set < unsigned >, automaton::VisiblyPushdownDPDA < >, string::LinearString < > > ( Occurrences::occurrences );
-
-std::set < unsigned > Occurrences::occurrences ( const automaton::RealTimeHeightDeterministicDPDA < > & automaton, const string::LinearString < > & string ) {
-	std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > res = Run::calculateState ( automaton, string );
-
-	return std::get < 2 > ( res );
-}
-
 auto OccurrencesRealTimeHeightDeterministicDPDALinearString = Occurrences::RegistratorWrapper < std::set < unsigned >, automaton::RealTimeHeightDeterministicDPDA < >, string::LinearString < > > ( Occurrences::occurrences );
-
-std::set < unsigned > Occurrences::occurrences ( const automaton::DPDA < > & automaton, const string::LinearString < > & string ) {
-	std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > res = Run::calculateState ( automaton, string );
-
-	return std::get < 2 > ( res );
-}
-
 auto OccurrencesDPDALinearString = Occurrences::RegistratorWrapper < std::set < unsigned >, automaton::DPDA < >, string::LinearString < > > ( Occurrences::occurrences );
 
 } /* namespace run */
diff --git a/alib2algo/src/automaton/run/Occurrences.h b/alib2algo/src/automaton/run/Occurrences.h
index ba6db00688..a95b4f913e 100644
--- a/alib2algo/src/automaton/run/Occurrences.h
+++ b/alib2algo/src/automaton/run/Occurrences.h
@@ -15,6 +15,17 @@
 #include <string/LinearString.h>
 #include <tree/ranked/RankedTree.h>
 
+#include "Run.h"
+#include <automaton/FSM/DFA.h>
+#include <automaton/FSM/NFA.h>
+#include <automaton/TA/DFTA.h>
+#include <automaton/PDA/InputDrivenDPDA.h>
+#include <automaton/PDA/VisiblyPushdownDPDA.h>
+#include <automaton/PDA/RealTimeHeightDeterministicDPDA.h>
+#include <automaton/PDA/DPDA.h>
+
+#include <deque>
+
 namespace automaton {
 
 namespace run {
@@ -29,15 +40,63 @@ public:
 	static std::set < unsigned > occurrences ( const automaton::Automaton & automaton, const string::LinearString < > & string );
 	static std::set < unsigned > occurrences ( const automaton::Automaton & automaton, const tree::RankedTree < > & string );
 
-	static std::set < unsigned > occurrences ( const automaton::DFA<> & automaton, const string::LinearString < > & string );
-	static std::set < unsigned > occurrences ( const automaton::DFTA < > & automaton, const tree::RankedTree < > & tree );
-	static std::set < unsigned > occurrences ( const automaton::InputDrivenDPDA < > & automaton, const string::LinearString < > & string );
-	static std::set < unsigned > occurrences ( const automaton::VisiblyPushdownDPDA < > & automaton, const string::LinearString < > & string );
-	static std::set < unsigned > occurrences ( const automaton::RealTimeHeightDeterministicDPDA < > & automaton, const string::LinearString < > & string );
-	static std::set < unsigned > occurrences ( const automaton::DPDA < > & automaton, const string::LinearString < > & string );
+	template < class SymbolType, class StateType >
+	static std::set < unsigned > occurrences ( const automaton::DFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class RankType, class StateType >
+	static std::set < unsigned > occurrences ( const automaton::DFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree );
+	template < class SymbolType, class StateType >
+	static std::set < unsigned > occurrences ( const automaton::InputDrivenDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class StateType >
+	static std::set < unsigned > occurrences ( const automaton::VisiblyPushdownDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static std::set < unsigned > occurrences ( const automaton::RealTimeHeightDeterministicDPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static std::set < unsigned > occurrences ( const automaton::DPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string );
 
 };
 
+template < class SymbolType, class StateType >
+std::set < unsigned > Occurrences::occurrences ( const automaton::DFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	std::tuple < bool, StateType, std::set < unsigned > > res = Run::calculateState ( automaton, string );
+
+	return std::get < 2 > ( res );
+}
+
+template < class SymbolType, class RankType, class StateType >
+std::set < unsigned > Occurrences::occurrences ( const automaton::DFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree ) {
+	std::tuple < bool, StateType, std::set < unsigned > > res = Run::calculateState ( automaton, tree );
+
+	return std::get < 2 > ( res );
+}
+
+template < class SymbolType, class StateType >
+std::set < unsigned > Occurrences::occurrences ( const automaton::InputDrivenDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > res = Run::calculateState ( automaton, string );
+
+	return std::get < 2 > ( res );
+}
+
+template < class SymbolType, class StateType >
+std::set < unsigned > Occurrences::occurrences ( const automaton::VisiblyPushdownDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > res = Run::calculateState ( automaton, string );
+
+	return std::get < 2 > ( res );
+}
+
+template < class SymbolType, class EpsilonType, class StateType >
+std::set < unsigned > Occurrences::occurrences ( const automaton::RealTimeHeightDeterministicDPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > res = Run::calculateState ( automaton, string );
+
+	return std::get < 2 > ( res );
+}
+
+template < class SymbolType, class EpsilonType, class StateType >
+std::set < unsigned > Occurrences::occurrences ( const automaton::DPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > res = Run::calculateState ( automaton, string );
+
+	return std::get < 2 > ( res );
+}
+
 } /* namespace run */
 
 } /* namespace automaton */
diff --git a/alib2algo/src/automaton/run/Result.cpp b/alib2algo/src/automaton/run/Result.cpp
index e91d7be414..f6bbb9005c 100644
--- a/alib2algo/src/automaton/run/Result.cpp
+++ b/alib2algo/src/automaton/run/Result.cpp
@@ -6,84 +6,21 @@
  */
 
 #include "Result.h"
-#include "Run.h"
-#include <automaton/FSM/DFA.h>
-#include <automaton/TA/DFTA.h>
-#include <automaton/PDA/InputDrivenDPDA.h>
-#include <automaton/PDA/VisiblyPushdownDPDA.h>
-#include <automaton/PDA/RealTimeHeightDeterministicDPDA.h>
-#include <automaton/PDA/DPDA.h>
-#include <label/LabelSetLabel.h>
-
-#include <deque>
 
 namespace automaton {
 
 namespace run {
 
-label::Label Result::result ( const automaton::Automaton & automaton, const alib::Object & object, const label::Label & failLabel ) {
+DefaultStateType Result::result ( const automaton::Automaton & automaton, const alib::Object & object, const DefaultStateType & failLabel ) {
 	return dispatch ( automaton.getData ( ), object.getData ( ), failLabel );
 }
 
-label::Label Result::result ( const automaton::DFA < > & automaton, const string::LinearString < > & string, const label::Label & failLabel ) {
-	std::tuple < bool, label::Label, std::set < unsigned > > res = Run::calculateState ( automaton, string );
-
-	if ( std::get < 0 > ( res ) ) return std::get < 1 > ( res );
-
-	return failLabel;
-}
-
-auto ResultDFALinearString = Result::RegistratorWrapper < label::Label, automaton::DFA<>, string::LinearString < > > ( Result::result );
-
-label::Label Result::result ( const automaton::DFTA < > & automaton, const tree::RankedTree < > & tree, const label::Label & failLabel ) {
-	std::tuple < bool, label::Label, std::set < unsigned > > res = Run::calculateState ( automaton, tree );
-
-	if ( std::get < 0 > ( res ) ) return std::get < 1 > ( res );
-
-	return failLabel;
-}
-
-auto ResultDFTARankedTree = Result::RegistratorWrapper < label::Label, automaton::DFTA < >, tree::RankedTree < > > ( Result::result );
-
-label::Label Result::result ( const automaton::InputDrivenDPDA < > & automaton, const string::LinearString < > & string, const label::Label & failLabel ) {
-	std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > res = Run::calculateState ( automaton, string );
-
-	if ( std::get < 0 > ( res ) ) return std::get < 1 > ( res );
-
-	return failLabel;
-}
-
-auto ResultInputDrivenDPDALinearString = Result::RegistratorWrapper < label::Label, automaton::InputDrivenDPDA < >, string::LinearString < > > ( Result::result );
-
-label::Label Result::result ( const automaton::VisiblyPushdownDPDA < > & automaton, const string::LinearString < > & string, const label::Label & failLabel ) {
-	std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > res = Run::calculateState ( automaton, string );
-
-	if ( std::get < 0 > ( res ) ) return std::get < 1 > ( res );
-
-	return failLabel;
-}
-
-auto ResultVisiblyPushdownDPDALinearString = Result::RegistratorWrapper < label::Label, automaton::VisiblyPushdownDPDA < >, string::LinearString < > > ( Result::result );
-
-label::Label Result::result ( const automaton::RealTimeHeightDeterministicDPDA < > & automaton, const string::LinearString < > & string, const label::Label & failLabel ) {
-	std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > res = Run::calculateState ( automaton, string );
-
-	if ( std::get < 0 > ( res ) ) return std::get < 1 > ( res );
-
-	return failLabel;
-}
-
-auto ResultRealTimeHeightDeterministicDPDALinearString = Result::RegistratorWrapper < label::Label, automaton::RealTimeHeightDeterministicDPDA < >, string::LinearString < > > ( Result::result );
-
-label::Label Result::result ( const automaton::DPDA < > & automaton, const string::LinearString < > & string, const label::Label & failLabel ) {
-	std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > res = Run::calculateState ( automaton, string );
-
-	if ( std::get < 0 > ( res ) ) return std::get < 1 > ( res );
-
-	return failLabel;
-}
-
-auto ResultDPDALinearString = Result::RegistratorWrapper < label::Label, automaton::DPDA < >, string::LinearString < > > ( Result::result );
+auto ResultDFALinearString = Result::RegistratorWrapper < DefaultStateType, automaton::DFA < >, string::LinearString < > > ( Result::result );
+auto ResultDFTARankedTree = Result::RegistratorWrapper < DefaultStateType, automaton::DFTA < >, tree::RankedTree < > > ( Result::result );
+auto ResultInputDrivenDPDALinearString = Result::RegistratorWrapper < DefaultStateType, automaton::InputDrivenDPDA < >, string::LinearString < > > ( Result::result );
+auto ResultVisiblyPushdownDPDALinearString = Result::RegistratorWrapper < DefaultStateType, automaton::VisiblyPushdownDPDA < >, string::LinearString < > > ( Result::result );
+auto ResultRealTimeHeightDeterministicDPDALinearString = Result::RegistratorWrapper < DefaultStateType, automaton::RealTimeHeightDeterministicDPDA < >, string::LinearString < > > ( Result::result );
+auto ResultDPDALinearString = Result::RegistratorWrapper < DefaultStateType, automaton::DPDA < >, string::LinearString < > > ( Result::result );
 
 } /* namespace run */
 
diff --git a/alib2algo/src/automaton/run/Result.h b/alib2algo/src/automaton/run/Result.h
index 26117df7b7..bc6341fe7d 100644
--- a/alib2algo/src/automaton/run/Result.h
+++ b/alib2algo/src/automaton/run/Result.h
@@ -17,27 +17,98 @@
 #include <tree/ranked/RankedTree.h>
 #include <label/FailStateLabel.h>
 
+#include "Run.h"
+#include <automaton/FSM/DFA.h>
+#include <automaton/TA/DFTA.h>
+#include <automaton/PDA/InputDrivenDPDA.h>
+#include <automaton/PDA/VisiblyPushdownDPDA.h>
+#include <automaton/PDA/RealTimeHeightDeterministicDPDA.h>
+#include <automaton/PDA/DPDA.h>
+#include <label/LabelSetLabel.h>
+
+#include <deque>
+
 namespace automaton {
 
 namespace run {
 
-class Result : public std::DoubleDispatch < Result, label::Label, const automaton::AutomatonBase &, const alib::ObjectBase &, const label::Label & > {
+class Result : public std::DoubleDispatch < Result, DefaultStateType, const automaton::AutomatonBase &, const alib::ObjectBase &, const DefaultStateType & > {
 public:
 	/**
 	 * Performs conversion.
 	 * @return left regular grammar equivalent to source automaton.
 	 */
-	static label::Label result ( const automaton::Automaton & automaton, const alib::Object & object, const label::Label & failLabel = label::FailStateLabel::instance < label::Label > ( ) );
+	static DefaultStateType result ( const automaton::Automaton & automaton, const alib::Object & object, const DefaultStateType & failLabel = label::FailStateLabel::instance < DefaultStateType > ( ) );
 
-	static label::Label result ( const automaton::DFA < > & automaton, const string::LinearString < > & string, const label::Label & failLabel = label::FailStateLabel::instance < label::Label > ( ) );
-	static label::Label result ( const automaton::DFTA < > & automaton, const tree::RankedTree < > & tree, const label::Label & failLabel = label::FailStateLabel::instance < label::Label > ( ) );
-	static label::Label result ( const automaton::InputDrivenDPDA < > & automaton, const string::LinearString < > & string, const label::Label & failLabel = label::FailStateLabel::instance < label::Label > ( ) );
-	static label::Label result ( const automaton::VisiblyPushdownDPDA < > & automaton, const string::LinearString < > & string, const label::Label & failLabel = label::FailStateLabel::instance < label::Label > ( ) );
-	static label::Label result ( const automaton::RealTimeHeightDeterministicDPDA < > & automaton, const string::LinearString < > & string, const label::Label & failLabel = label::FailStateLabel::instance < label::Label > ( ) );
-	static label::Label result ( const automaton::DPDA < > & automaton, const string::LinearString < > & string, const label::Label & failLabel = label::FailStateLabel::instance < label::Label > ( ) );
+	template < class SymbolType, class StateType >
+	static StateType result ( const automaton::DFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string, const StateType & failLabel = label::FailStateLabel::instance < StateType > ( ) );
+	template < class SymbolType, class RankType, class StateType >
+	static StateType result ( const automaton::DFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree, const StateType & failLabel = label::FailStateLabel::instance < StateType > ( ) );
+	template < class SymbolType, class StateType >
+	static StateType result ( const automaton::InputDrivenDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string, const StateType & failLabel = label::FailStateLabel::instance < StateType > ( ) );
+	template < class SymbolType, class StateType >
+	static StateType result ( const automaton::VisiblyPushdownDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string, const StateType & failLabel = label::FailStateLabel::instance < StateType > ( ) );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static StateType result ( const automaton::RealTimeHeightDeterministicDPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string, const StateType & failLabel = label::FailStateLabel::instance < StateType > ( ) );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static StateType result ( const automaton::DPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string, const StateType & failLabel = label::FailStateLabel::instance < StateType > ( ) );
 
 };
 
+template < class SymbolType, class StateType >
+StateType Result::result ( const automaton::DFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string, const StateType & failLabel ) {
+	std::tuple < bool, StateType, std::set < unsigned > > res = Run::calculateState ( automaton, string );
+
+	if ( std::get < 0 > ( res ) ) return std::get < 1 > ( res );
+
+	return failLabel;
+}
+
+template < class SymbolType, class RankType, class StateType >
+StateType Result::result ( const automaton::DFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree, const StateType & failLabel ) {
+	std::tuple < bool, StateType, std::set < unsigned > > res = Run::calculateState ( automaton, tree );
+
+	if ( std::get < 0 > ( res ) ) return std::get < 1 > ( res );
+
+	return failLabel;
+}
+
+template < class SymbolType, class StateType >
+StateType Result::result ( const automaton::InputDrivenDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string, const StateType & failLabel ) {
+	std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > res = Run::calculateState ( automaton, string );
+
+	if ( std::get < 0 > ( res ) ) return std::get < 1 > ( res );
+
+	return failLabel;
+}
+
+template < class SymbolType, class StateType >
+StateType Result::result ( const automaton::VisiblyPushdownDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string, const StateType & failLabel ) {
+	std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > res = Run::calculateState ( automaton, string );
+
+	if ( std::get < 0 > ( res ) ) return std::get < 1 > ( res );
+
+	return failLabel;
+}
+
+template < class SymbolType, class EpsilonType, class StateType >
+StateType Result::result ( const automaton::RealTimeHeightDeterministicDPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string, const StateType & failLabel ) {
+	std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > res = Run::calculateState ( automaton, string );
+
+	if ( std::get < 0 > ( res ) ) return std::get < 1 > ( res );
+
+	return failLabel;
+}
+
+template < class SymbolType, class EpsilonType, class StateType >
+StateType Result::result ( const automaton::DPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string, const StateType & failLabel ) {
+	std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > res = Run::calculateState ( automaton, string );
+
+	if ( std::get < 0 > ( res ) ) return std::get < 1 > ( res );
+
+	return failLabel;
+}
+
 } /* namespace run */
 
 } /* namespace automaton */
diff --git a/alib2algo/src/automaton/run/Run.cpp b/alib2algo/src/automaton/run/Run.cpp
deleted file mode 100644
index 10caa1614f..0000000000
--- a/alib2algo/src/automaton/run/Run.cpp
+++ /dev/null
@@ -1,570 +0,0 @@
-/*
- * Accept.cpp
- *
- *  Created on: 9. 2. 2014
- *	  Author: Jan Travnicek
- */
-
-#include "Run.h"
-#include <automaton/FSM/DFA.h>
-#include <automaton/FSM/NFA.h>
-#include <automaton/TA/DFTA.h>
-#include <automaton/TA/NFTA.h>
-#include <automaton/PDA/InputDrivenDPDA.h>
-#include <automaton/PDA/VisiblyPushdownDPDA.h>
-#include <automaton/PDA/RealTimeHeightDeterministicDPDA.h>
-#include <automaton/PDA/DPDA.h>
-#include <automaton/PDA/NPDTA.h>
-#include <global/GlobalData.h>
-
-#include <label/FailStateLabel.h>
-
-#include <deque>
-#include <algorithm>
-#include <iterator>
-
-namespace automaton {
-
-namespace run {
-
-// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-std::tuple < bool, label::Label, std::set < unsigned > > Run::calculateState ( const automaton::DFA < > & automaton, const string::LinearString < > & string ) {
-	bool res = true;
-	unsigned i = 0;
-	std::set < unsigned > occurrences;
-	label::Label state = automaton.getInitialState ( );
-
-	if ( automaton.getFinalStates ( ).count ( state ) )
-		occurrences.insert ( i );
-
-	if ( common::GlobalData::verbose )
-		std::clog << state << std::endl;
-
-	for ( const alphabet::Symbol & symbol : string.getContent ( ) ) {
-		auto transition = automaton.getTransitions ( ).find ( std::make_pair ( state, symbol ) );
-
-		if ( transition == automaton.getTransitions ( ).end ( ) ) {
-			res = false;
-			break;
-		}
-
-		state = transition->second;
-		i++;
-
-		if ( automaton.getFinalStates ( ).count ( state ) )
-			occurrences.insert ( i );
-
-		if ( common::GlobalData::verbose )
-			std::clog << state << std::endl;
-	}
-
-	return std::make_tuple ( res, state, occurrences );
-}
-
-// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-std::tuple < bool, std::set < label::Label >, std::set < unsigned > > Run::calculateStates ( const automaton::NFA < > & automaton, const string::LinearString < > & string ) {
-	bool res = true;
-	unsigned i = 0;
-	std::set < unsigned > occurrences;
-	std::set < label::Label > states {
-		automaton.getInitialState ( )
-	};
-
-	for ( const label::Label & state : states )
-		if ( automaton.getFinalStates ( ).count ( state ) )
-			occurrences.insert ( i );
-
-	if ( common::GlobalData::verbose )
-		std::clog << states << std::endl;
-
-	for ( const alphabet::Symbol & symbol : string.getContent ( ) ) {
-		std::set < label::Label > next;
-
-		for ( const label::Label & state : states ) {
-			auto transitions = automaton.getTransitions ( ).find ( std::make_pair ( state, symbol ) );
-
-			if ( transitions == automaton.getTransitions ( ).end ( ) ) continue;
-
-			next.insert ( transitions->second.begin ( ), transitions->second.end ( ) );
-		}
-
-		i++;
-		states = next;
-
-		for ( const label::Label & state : states )
-			if ( automaton.getFinalStates ( ).count ( state ) )
-				occurrences.insert ( i );
-
-		if ( common::GlobalData::verbose )
-			std::clog << states << std::endl;
-	}
-
-	return std::make_tuple ( res, states, occurrences );
-}
-
-// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-std::pair < bool, label::Label > Run::calculateState ( const automaton::DFTA < > & automaton, const std::tree < std::ranked_symbol < > > & node, std::set < unsigned > & occ, unsigned & i ) {
-	std::vector < label::Label > states;
-
-	states.reserve ( ( size_t ) node.getData ( ).getRank ( ) );
-
-	unsigned tmp = i;
-	i++;
-
-	bool sign = true;
-
-	for ( const std::tree < std::ranked_symbol < > > & child : node.getChildren ( ) ) {
-		std::pair < bool, label::Label > res = calculateState ( automaton, child, occ, i );
-
-		if ( res.first == false )
-			sign = false;
-		else
-			states.push_back ( res.second );
-	}
-
-	if ( !sign ) return std::make_pair ( false, label::FailStateLabel::instance < label::Label > ( ) );
-
-	const auto & it = automaton.getTransitions ( ).find ( std::make_pair ( node.getData ( ), states ) );
-
-	if ( it == automaton.getTransitions ( ).end ( ) ) return std::make_pair ( false, label::FailStateLabel::instance < label::Label > ( ) );
-
-	label::Label state = it->second;
-
-	if ( automaton.getFinalStates ( ).count ( state ) ) occ.insert ( tmp );
-
-	if ( common::GlobalData::verbose )
-		std::clog << state << std::endl;
-
-	return std::make_pair ( true, state );
-}
-
-std::tuple < bool, label::Label, std::set < unsigned > > Run::calculateState ( const automaton::DFTA < > & automaton, const tree::RankedTree < > & tree ) {
-	std::set < unsigned > occ;
-	unsigned i = 0;
-	std::pair < bool, label::Label > res = calculateState ( automaton, tree.getContent ( ), occ, i );
-
-	return std::make_tuple ( res.first, res.second, occ );
-}
-
-// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-std::pair < bool, std::set < label::Label > > Run::calculateStates ( const automaton::NFTA < > & automaton, const std::tree < std::ranked_symbol < > > & node, std::set < unsigned > & occ, unsigned & i ) {
-	std::vector < std::set < label::Label > > resStates;
-
-	resStates.reserve ( ( size_t ) node.getData ( ).getRank ( ) );
-
-	unsigned tmp = i;
-	i++;
-
-	bool sign = true;
-
-	for ( const std::tree < std::ranked_symbol < > > & child : node.getChildren ( ) ) {
-		std::pair < bool, std::set < label::Label > > childStates = calculateStates ( automaton, child, occ, i );
-
-		if ( childStates.second.empty ( ) )
-			sign = false;
-
-		resStates.push_back ( childStates.second );
-	}
-
-	std::set < label::Label > states;
-
-	for ( const auto & transition : automaton.getTransitions ( ) ) {
-		if ( transition.first.first != node.getData ( ) )
-			continue;
-
-		unsigned rank = ( unsigned ) transition.first.first.getRank ( );
-		unsigned j;
-
-		for ( j = 0; j < rank; j++ )
-			if ( !resStates[j].count ( transition.first.second[j] ) )
-				break;
-
-		if ( j == rank )
-			states.insert ( transition.second.begin ( ), transition.second.end ( ) );
-	}
-
-	for ( const label::Label & state : states )
-		if ( automaton.getFinalStates ( ).count ( state ) ) occ.insert ( tmp );
-
-	if ( common::GlobalData::verbose )
-		std::clog << states << std::endl;
-
-	return std::make_pair ( sign, states );
-}
-
-std::tuple < bool, std::set < label::Label >, std::set < unsigned > > Run::calculateStates ( const automaton::NFTA < > & automaton, const tree::RankedTree < > & tree ) {
-	std::set < unsigned > occ;
-	unsigned i = 0;
-	std::pair < bool, std::set < label::Label > > res = calculateStates ( automaton, tree.getContent ( ), occ, i );
-
-	return std::make_tuple ( res.first, res.second, occ );
-}
-
-// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-bool Run::canPop ( const std::deque < alphabet::Symbol > & pushdownStore, const std::vector < alphabet::Symbol > & pop ) {
-	unsigned popSize = pop.size ( );
-	unsigned pushdownStoreSize = pushdownStore.size ( );
-
-	if ( pushdownStoreSize < popSize ) return false;
-
-	for ( unsigned i = 0; i < popSize; i++ )
-		if ( pop[i] != pushdownStore[pushdownStoreSize - i - 1] )
-			return false;
-
-	return true;
-}
-
-// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > Run::calculateState ( const automaton::InputDrivenDPDA < > & automaton, const string::LinearString < > & string ) {
-	label::Label state = automaton.getInitialState ( );
-	std::deque < alphabet::Symbol > pushdownStore {
-		automaton.getInitialSymbol ( )
-	};
-	unsigned i = 0;
-	std::set < unsigned > occ;
-	bool res = true;
-
-	if ( automaton.getFinalStates ( ).count ( state ) )
-		occ.insert ( i );
-
-	if ( common::GlobalData::verbose )
-		std::clog << state << std::endl;
-
-	for ( const alphabet::Symbol & symbol : string.getContent ( ) ) {
-		auto transition = automaton.getTransitions ( ).find ( std::make_pair ( state, symbol ) );
-
-		if ( transition == automaton.getTransitions ( ).end ( ) ) {
-			res = false;
-			break;
-		}
-
-		const std::pair < std::vector < alphabet::Symbol >, std::vector < alphabet::Symbol > > & operation = automaton.getPushdownStoreOperations ( ).find ( symbol )->second;
-
-		if ( !canPop ( pushdownStore, operation.first ) ) {
-			res = false;
-			break;
-		}
-
-		for ( unsigned j = 0; j < operation.first.size ( ); j++ ) pushdownStore.pop_back ( );
-
-		for ( const auto & push : std::make_reverse ( operation.second ) ) pushdownStore.push_back ( push );
-
-		state = transition->second;
-		i++;
-
-		if ( automaton.getFinalStates ( ).count ( state ) )
-			occ.insert ( i );
-
-		if ( common::GlobalData::verbose )
-			std::clog << state << std::endl;
-	}
-
-	return std::make_tuple ( res, state, occ, pushdownStore );
-}
-
-// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > Run::calculateState ( const automaton::VisiblyPushdownDPDA < > & automaton, const string::LinearString < > & string ) {
-	label::Label state = automaton.getInitialState ( );
-	std::deque < alphabet::Symbol > pushdownStore {
-		automaton.getBottomOfTheStackSymbol ( )
-	};
-	unsigned i = 0;
-	std::set < unsigned > occ;
-	bool res = true;
-
-	if ( automaton.getFinalStates ( ).count ( state ) )
-		occ.insert ( i );
-
-	if ( common::GlobalData::verbose )
-		std::clog << state << std::endl;
-
-	for ( const alphabet::Symbol & symbol : string.getContent ( ) ) {
-		if ( automaton.getCallInputAlphabet ( ).count ( symbol ) ) {
-			auto transition = automaton.getCallTransitions ( ).find ( std::make_pair ( state, symbol ) );
-
-			if ( transition == automaton.getCallTransitions ( ).end ( ) ) {
-				res = false;
-				break;
-			}
-
-			pushdownStore.push_back ( transition->second.second );
-			state = transition->second.first;
-		} else if ( automaton.getReturnInputAlphabet ( ).count ( symbol ) ) {
-			auto transition = automaton.getReturnTransitions ( ).find ( std::make_tuple ( state, symbol, pushdownStore.back ( ) ) );
-
-			if ( transition == automaton.getReturnTransitions ( ).end ( ) ) {
-				res = false;
-				break;
-			}
-
-			if ( pushdownStore.back ( ) != automaton.getBottomOfTheStackSymbol ( ) ) pushdownStore.pop_back ( );
-
-			state = transition->second;
-		} else if ( automaton.getLocalInputAlphabet ( ).count ( symbol ) ) {
-			auto transition = automaton.getLocalTransitions ( ).find ( std::make_pair ( state, symbol ) );
-
-			if ( transition == automaton.getLocalTransitions ( ).end ( ) ) {
-				res = false;
-				break;
-			}
-
-			state = transition->second;
-		} else {
-			res = false;
-			break;
-		}
-
-		i++;
-
-		if ( automaton.getFinalStates ( ).count ( state ) )
-			occ.insert ( i );
-
-		if ( common::GlobalData::verbose )
-			std::clog << state << std::endl;
-	}
-
-	return std::make_tuple ( res, state, occ, pushdownStore );
-}
-
-// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > Run::calculateState ( const automaton::RealTimeHeightDeterministicDPDA < > & automaton, const string::LinearString < > & string ) {
-	label::Label state = automaton.getInitialState ( );
-	std::deque < alphabet::Symbol > pushdownStore {
-		automaton.getBottomOfTheStackSymbol ( )
-	};
-	unsigned i = 0;
-	std::set < unsigned > occ;
-	bool res = true;
-
-	if ( automaton.getFinalStates ( ).count ( state ) )
-		occ.insert ( i );
-
-	if ( common::GlobalData::verbose )
-		std::clog << state << std::endl;
-
-	for ( auto symbolIter = string.getContent ( ).begin ( ); symbolIter != string.getContent ( ).end ( ); ) {
-
-		auto callTransition = automaton.getCallTransitions ( ).find ( std::make_pair ( state, * symbolIter ) );
-
-		if ( callTransition != automaton.getCallTransitions ( ).end ( ) ) {
-			symbolIter++;
-			i++;
-		} else {
-			callTransition = automaton.getCallTransitions ( ).find ( std::make_pair ( state, string::Epsilon < >::EPSILON ) );
-		}
-
-		if ( callTransition != automaton.getCallTransitions ( ).end ( ) ) {
-			pushdownStore.push_back ( callTransition->second.second );
-			state = callTransition->second.first;
-		} else {
-			res = false;
-		}
-
-		if ( !res ) {
-			auto returnTransition = automaton.getReturnTransitions ( ).find ( std::make_tuple ( state, * symbolIter, pushdownStore.back ( ) ) );
-
-			if ( returnTransition != automaton.getReturnTransitions ( ).end ( ) ) {
-				symbolIter++;
-				i++;
-			} else {
-				returnTransition = automaton.getReturnTransitions ( ).find ( std::make_tuple ( state, string::Epsilon < >::EPSILON, pushdownStore.back ( ) ) );
-			}
-
-			if ( returnTransition != automaton.getReturnTransitions ( ).end ( ) ) {
-				pushdownStore.pop_back ( );
-				state = returnTransition->second;
-			} else {
-				res = false;
-			}
-		}
-
-		if ( !res ) {
-			auto localTransition = automaton.getLocalTransitions ( ).find ( std::make_pair ( state, * symbolIter ) );
-
-			if ( localTransition != automaton.getLocalTransitions ( ).end ( ) ) {
-				symbolIter++;
-				i++;
-			} else {
-				localTransition = automaton.getLocalTransitions ( ).find ( std::make_pair ( state, string::Epsilon < >::EPSILON ) );
-			}
-
-			if ( localTransition != automaton.getLocalTransitions ( ).end ( ) )
-				state = localTransition->second;
-			else
-				res = false;
-		}
-
-		if ( automaton.getFinalStates ( ).count ( state ) )
-			occ.insert ( i );
-
-		if ( common::GlobalData::verbose )
-			std::clog << state << std::endl;
-
-		if ( res == false )
-			break;
-	}
-
-	return std::make_tuple ( res, state, occ, pushdownStore );
-}
-
-// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > Run::calculateState ( const automaton::DPDA < > & automaton, const string::LinearString < > & string ) {
-	label::Label state = automaton.getInitialState ( );
-	std::deque < alphabet::Symbol > pushdownStore {
-		automaton.getInitialSymbol ( )
-	};
-	unsigned i = 0;
-	std::set < unsigned > occ;
-	bool res = true;
-
-	if ( automaton.getFinalStates ( ).count ( state ) )
-		occ.insert ( i );
-
-	if ( common::GlobalData::verbose ) {
-		std::clog << "State : " << state << std::endl;
-		std::clog << "PushdownStore : " << pushdownStore << std::endl;
-	}
-
-	for ( auto symbolIter = string.getContent ( ).begin ( ); symbolIter != string.getContent ( ).end ( ); ) {
-		auto transitions = automaton.getTransitionsFromState ( state );
-		auto transition	 = transitions.begin ( );
-
-		for ( ; transition != transitions.end ( ); transition++ ) {
-			if ( ( std::get < 1 > ( transition->first ) != * symbolIter ) && !std::get < 1 > ( transition->first ).is < string::Epsilon < > > ( ) ) continue;
-
-			if ( canPop ( pushdownStore, std::get < 2 > ( transition->first ) ) ) break;
-		}
-
-		if ( transition == transitions.end ( ) ) {
-			res = false;
-			break;
-		}
-
-		if ( common::GlobalData::verbose )
-			std::clog << "Transition: " << * transition << std::endl;
-
-		for ( unsigned j = 0; j < std::get < 2 > ( transition->first ).size ( ); j++ ) pushdownStore.pop_back ( );
-
-		for ( const auto & symbol : std::make_reverse ( transition->second.second ) ) pushdownStore.push_back ( symbol );
-
-		state = transition->second.first;
-
-		if ( !std::get < 1 > ( transition->first ).is < string::Epsilon < > > ( ) ) {
-			i++;
-			symbolIter++;
-		}
-
-		if ( automaton.getFinalStates ( ).count ( state ) )
-			occ.insert ( i );
-
-		if ( common::GlobalData::verbose ) {
-			std::clog << "State: " << state << std::endl;
-			std::clog << "PushdownStore: " << pushdownStore << std::endl;
-		}
-	}
-
-	return std::make_tuple ( res, state, occ, pushdownStore );
-}
-
-// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-struct graphStructuredStack {
-	graphStructuredStack ( std::shared_ptr < graphStructuredStack > parent, alphabet::Symbol data ) : m_parent(parent), m_data(data) {}
-	std::shared_ptr < graphStructuredStack > m_parent;
-	alphabet::Symbol m_data;
-};
-
-std::tuple < bool, std::set < label::Label >, std::set < std::vector < alphabet::Symbol > > > Run::calculateStates ( const automaton::NPDTA < > & automaton, const string::LinearString < > & string ) {
-	bool res = false;
-	unsigned i = 0;
-	std::set < unsigned > occurrences;
-	label::Label state = automaton . getInitialState ();
-	std::vector<alphabet::Symbol>::const_iterator symbolIter = string . getContent () . begin ();
-	std::shared_ptr < graphStructuredStack > stackNode = std::make_shared < graphStructuredStack > ( nullptr, * symbolIter );
-	std::shared_ptr < graphStructuredStack > outputNode = std::make_shared < graphStructuredStack > ( nullptr, * symbolIter );
-
-	if ( automaton . getFinalStates () . count ( state ) ) {
-		occurrences . insert ( i );
-	}
-
-	std::deque < std::tuple < label::Label, std::vector<alphabet::Symbol>::const_iterator, std::shared_ptr < graphStructuredStack >, std::shared_ptr < graphStructuredStack > > > bftQueue;
-	auto configuration = std::make_tuple ( state, symbolIter, stackNode, outputNode );
-	bftQueue . push_back ( configuration );
-
-	std::set < std::vector < alphabet::Symbol > > allOutputs;
-	std::set < label::Label > states;
-
-	while ( ! bftQueue . empty () ) {
-		configuration = bftQueue . front (); bftQueue . pop_front ();
-		state = std::get<0>(configuration);
-		symbolIter = std::get<1>(configuration);
-		stackNode = std::get<2>(configuration);
-		outputNode = std::get<3>(configuration);
-
-		if ( symbolIter == string . getContent () . end () ) {
-			states . insert ( state );
-			if ( automaton . getFinalStates () . count ( state ) && stackNode -> m_parent == NULL ) {
-				res = true;
-				std::vector < alphabet::Symbol > output;
-				while ( outputNode->m_parent != NULL ) {
-					output . push_back ( outputNode->m_data );
-					outputNode = outputNode -> m_parent;
-				}
-				std::reverse ( output.begin(), output.end() );
-				allOutputs . insert ( output );
-			}
-			continue;
-		}
-
-		for ( const auto & transition : automaton . getTransitionsFromState ( state ) ) {
-			if ( std::get<1>(transition . first) != * symbolIter && ! std::get<1>(transition . first) . is<string::Epsilon < >>() )
-				continue;
-
-			const auto & pop = std::get<2>(transition . first);
-			std::shared_ptr < graphStructuredStack > stackNodeCopy = stackNode;
-			std::shared_ptr < graphStructuredStack > outputNodeCopy = outputNode;
-
-			unsigned j = 0;
-			for ( ; j < pop . size (); j ++ ) {
-				if ( stackNodeCopy->m_parent == NULL || stackNodeCopy->m_data != pop . at (j) ) {
-					break;
-				}
-				stackNodeCopy = stackNodeCopy -> m_parent;
-			}
-			if ( j == pop . size () ) {
-				for ( const auto & elem : std::make_reverse ( std::get<1>(transition . second ) ) ) {
-					stackNodeCopy = std::make_shared < graphStructuredStack > ( stackNodeCopy, elem );
-				}
-				for ( const auto & elem : std::get<2>(transition . second) ) {
-					outputNodeCopy = std::make_shared < graphStructuredStack > ( outputNodeCopy, elem );
-				}
-
-				if ( ! std::get<1>(transition . first) . is<string::Epsilon < >>() ) {
-					configuration = std::make_tuple ( std::get<0>(transition . second), symbolIter + 1, stackNodeCopy, outputNodeCopy );
-				} else {
-					configuration = std::make_tuple ( std::get<0>(transition . second), symbolIter, stackNodeCopy, outputNodeCopy );
-				}
-				bftQueue . push_back ( configuration );
-			} else {
-				states . insert ( state );
-			}
-		}
-	}
-
-	return std::make_tuple ( res, states, allOutputs );
-}
-
-// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-
-} /* namespace run */
-
-} /* namespace automaton */
diff --git a/alib2algo/src/automaton/run/Run.h b/alib2algo/src/automaton/run/Run.h
index 82ec3157a0..96e4bec98a 100644
--- a/alib2algo/src/automaton/run/Run.h
+++ b/alib2algo/src/automaton/run/Run.h
@@ -12,30 +12,608 @@
 #include <automaton/AutomatonFeatures.h>
 #include <string/LinearString.h>
 #include <tree/ranked/RankedTree.h>
-#include <alphabet/Symbol.h>
-#include <label/Label.h>
+
+#include <automaton/FSM/DFA.h>
+#include <automaton/FSM/NFA.h>
+#include <automaton/TA/DFTA.h>
+#include <automaton/TA/NFTA.h>
+#include <automaton/PDA/InputDrivenDPDA.h>
+#include <automaton/PDA/VisiblyPushdownDPDA.h>
+#include <automaton/PDA/RealTimeHeightDeterministicDPDA.h>
+#include <automaton/PDA/DPDA.h>
+#include <automaton/PDA/NPDTA.h>
+#include <global/GlobalData.h>
+
+#include <label/FailStateLabel.h>
+
+#include <deque>
+#include <algorithm>
+#include <iterator>
 
 namespace automaton {
 
 namespace run {
 
 class Run {
-	static std::pair < bool, label::Label > calculateState ( const automaton::DFTA < > & automaton, const std::tree < std::ranked_symbol < > > & node, std::set < unsigned > & occ, unsigned & i );
-	static std::pair < bool, std::set < label::Label > > calculateStates ( const automaton::NFTA < > & automaton, const std::tree < std::ranked_symbol < > > & node, std::set < unsigned > & occ, unsigned & i );
-	static bool canPop ( const std::deque < alphabet::Symbol > & pushdownStore, const std::vector < alphabet::Symbol > & pop );
+	template < class SymbolType, class RankType, class StateType >
+	static std::pair < bool, StateType > calculateState ( const automaton::DFTA < SymbolType, RankType, StateType > & automaton, const std::tree < std::ranked_symbol < SymbolType, RankType > > & node, std::set < unsigned > & occ, unsigned & i );
+	template < class SymbolType, class RankType, class StateType >
+	static std::pair < bool, std::set < StateType > > calculateStates ( const automaton::NFTA < SymbolType, RankType, StateType > & automaton, const std::tree < std::ranked_symbol < SymbolType, RankType > > & node, std::set < unsigned > & occ, unsigned & i );
+	template < class SymbolType >
+	static bool canPop ( const std::deque < SymbolType > & pushdownStore, const std::vector < SymbolType > & pop );
 
 public:
-	static std::tuple < bool, label::Label, std::set < unsigned > > calculateState ( const automaton::DFA < > & automaton, const string::LinearString < > & string );
-	static std::tuple < bool, std::set < label::Label >, std::set < unsigned > > calculateStates ( const automaton::NFA < > & automaton, const string::LinearString < > & string );
-	static std::tuple < bool, label::Label, std::set < unsigned > > calculateState ( const automaton::DFTA < > & automaton, const tree::RankedTree < > & tree );
-	static std::tuple < bool, std::set < label::Label >, std::set < unsigned > > calculateStates ( const automaton::NFTA < > & automaton, const tree::RankedTree < > & tree );
-	static std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > calculateState ( const automaton::InputDrivenDPDA < > & automaton, const string::LinearString < > & string );
-	static std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > calculateState ( const automaton::VisiblyPushdownDPDA < > & automaton, const string::LinearString < > & string );
-	static std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > calculateState ( const automaton::RealTimeHeightDeterministicDPDA < > & automaton, const string::LinearString < > & string );
-	static std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > calculateState ( const automaton::DPDA < > & automaton, const string::LinearString < > & string );
-	static std::tuple < bool, std::set < label::Label >, std::set < std::vector < alphabet::Symbol > > > calculateStates ( const automaton::NPDTA < > & automaton, const string::LinearString < > & string );
+	template < class SymbolType, class StateType >
+	static std::tuple < bool, StateType, std::set < unsigned > > calculateState ( const automaton::DFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class StateType >
+	static std::tuple < bool, std::set < StateType >, std::set < unsigned > > calculateStates ( const automaton::NFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class RankType, class StateType >
+	static std::tuple < bool, StateType, std::set < unsigned > > calculateState ( const automaton::DFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree );
+	template < class SymbolType, class RankType, class StateType >
+	static std::tuple < bool, std::set < StateType >, std::set < unsigned > > calculateStates ( const automaton::NFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree );
+	template < class SymbolType, class StateType >
+	static std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > calculateState ( const automaton::InputDrivenDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class StateType >
+	static std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > calculateState ( const automaton::VisiblyPushdownDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > calculateState ( const automaton::RealTimeHeightDeterministicDPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > calculateState ( const automaton::DPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static std::tuple < bool, std::set < StateType >, std::set < std::vector < SymbolType > > > calculateStates ( const automaton::NPDTA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string );
 };
 
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+template < class SymbolType, class StateType >
+std::tuple < bool, StateType, std::set < unsigned > > Run::calculateState ( const automaton::DFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	bool res = true;
+	unsigned i = 0;
+	std::set < unsigned > occurrences;
+	StateType state = automaton.getInitialState ( );
+
+	if ( automaton.getFinalStates ( ).count ( state ) )
+		occurrences.insert ( i );
+
+	if ( common::GlobalData::verbose )
+		std::clog << state << std::endl;
+
+	for ( const SymbolType & symbol : string.getContent ( ) ) {
+		auto transition = automaton.getTransitions ( ).find ( std::make_pair ( state, symbol ) );
+
+		if ( transition == automaton.getTransitions ( ).end ( ) ) {
+			res = false;
+			break;
+		}
+
+		state = transition->second;
+		i++;
+
+		if ( automaton.getFinalStates ( ).count ( state ) )
+			occurrences.insert ( i );
+
+		if ( common::GlobalData::verbose )
+			std::clog << state << std::endl;
+	}
+
+	return std::make_tuple ( res, state, occurrences );
+}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+template < class SymbolType, class StateType >
+std::tuple < bool, std::set < StateType >, std::set < unsigned > > Run::calculateStates ( const automaton::NFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	bool res = true;
+	unsigned i = 0;
+	std::set < unsigned > occurrences;
+	std::set < StateType > states {
+		automaton.getInitialState ( )
+	};
+
+	for ( const StateType & state : states )
+		if ( automaton.getFinalStates ( ).count ( state ) )
+			occurrences.insert ( i );
+
+	if ( common::GlobalData::verbose )
+		std::clog << states << std::endl;
+
+	for ( const SymbolType & symbol : string.getContent ( ) ) {
+		std::set < StateType > next;
+
+		for ( const StateType & state : states ) {
+			auto transitions = automaton.getTransitions ( ).find ( std::make_pair ( state, symbol ) );
+
+			if ( transitions == automaton.getTransitions ( ).end ( ) ) continue;
+
+			next.insert ( transitions->second.begin ( ), transitions->second.end ( ) );
+		}
+
+		i++;
+		states = next;
+
+		for ( const StateType & state : states )
+			if ( automaton.getFinalStates ( ).count ( state ) )
+				occurrences.insert ( i );
+
+		if ( common::GlobalData::verbose )
+			std::clog << states << std::endl;
+	}
+
+	return std::make_tuple ( res, states, occurrences );
+}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+template < class SymbolType, class RankType, class StateType >
+std::pair < bool, StateType > Run::calculateState ( const automaton::DFTA < SymbolType, RankType, StateType > & automaton, const std::tree < std::ranked_symbol < SymbolType, RankType > > & node, std::set < unsigned > & occ, unsigned & i ) {
+	std::vector < StateType > states;
+
+	states.reserve ( ( size_t ) node.getData ( ).getRank ( ) );
+
+	unsigned tmp = i;
+	i++;
+
+	bool sign = true;
+
+	for ( const std::tree < std::ranked_symbol < SymbolType, RankType > > & child : node.getChildren ( ) ) {
+		std::pair < bool, StateType > res = calculateState ( automaton, child, occ, i );
+
+		if ( res.first == false )
+			sign = false;
+		else
+			states.push_back ( res.second );
+	}
+
+	if ( !sign ) return std::make_pair ( false, label::FailStateLabel::instance < StateType > ( ) );
+
+	const auto & it = automaton.getTransitions ( ).find ( std::make_pair ( node.getData ( ), states ) );
+
+	if ( it == automaton.getTransitions ( ).end ( ) ) return std::make_pair ( false, label::FailStateLabel::instance < StateType > ( ) );
+
+	StateType state = it->second;
+
+	if ( automaton.getFinalStates ( ).count ( state ) ) occ.insert ( tmp );
+
+	if ( common::GlobalData::verbose )
+		std::clog << state << std::endl;
+
+	return std::make_pair ( true, state );
+}
+
+template < class SymbolType, class RankType, class StateType >
+std::tuple < bool, StateType, std::set < unsigned > > Run::calculateState ( const automaton::DFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree ) {
+	std::set < unsigned > occ;
+	unsigned i = 0;
+	std::pair < bool, StateType > res = calculateState ( automaton, tree.getContent ( ), occ, i );
+
+	return std::make_tuple ( res.first, res.second, occ );
+}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+template < class SymbolType, class RankType, class StateType >
+std::pair < bool, std::set < StateType > > Run::calculateStates ( const automaton::NFTA < SymbolType, RankType, StateType > & automaton, const std::tree < std::ranked_symbol < SymbolType, RankType > > & node, std::set < unsigned > & occ, unsigned & i ) {
+	std::vector < std::set < StateType > > resStates;
+
+	resStates.reserve ( ( size_t ) node.getData ( ).getRank ( ) );
+
+	unsigned tmp = i;
+	i++;
+
+	bool sign = true;
+
+	for ( const std::tree < std::ranked_symbol < SymbolType, RankType > > & child : node.getChildren ( ) ) {
+		std::pair < bool, std::set < StateType > > childStates = calculateStates ( automaton, child, occ, i );
+
+		if ( childStates.second.empty ( ) )
+			sign = false;
+
+		resStates.push_back ( childStates.second );
+	}
+
+	std::set < StateType > states;
+
+	for ( const auto & transition : automaton.getTransitions ( ) ) {
+		if ( transition.first.first != node.getData ( ) )
+			continue;
+
+		unsigned rank = ( unsigned ) transition.first.first.getRank ( );
+		unsigned j;
+
+		for ( j = 0; j < rank; j++ )
+			if ( !resStates[j].count ( transition.first.second[j] ) )
+				break;
+
+		if ( j == rank )
+			states.insert ( transition.second.begin ( ), transition.second.end ( ) );
+	}
+
+	for ( const StateType & state : states )
+		if ( automaton.getFinalStates ( ).count ( state ) ) occ.insert ( tmp );
+
+	if ( common::GlobalData::verbose )
+		std::clog << states << std::endl;
+
+	return std::make_pair ( sign, states );
+}
+
+template < class SymbolType, class RankType, class StateType >
+std::tuple < bool, std::set < StateType >, std::set < unsigned > > Run::calculateStates ( const automaton::NFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree ) {
+	std::set < unsigned > occ;
+	unsigned i = 0;
+	std::pair < bool, std::set < StateType > > res = calculateStates ( automaton, tree.getContent ( ), occ, i );
+
+	return std::make_tuple ( res.first, res.second, occ );
+}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+template < class SymbolType >
+bool Run::canPop ( const std::deque < SymbolType > & pushdownStore, const std::vector < SymbolType > & pop ) {
+	unsigned popSize = pop.size ( );
+	unsigned pushdownStoreSize = pushdownStore.size ( );
+
+	if ( pushdownStoreSize < popSize ) return false;
+
+	for ( unsigned i = 0; i < popSize; i++ )
+		if ( pop[i] != pushdownStore[pushdownStoreSize - i - 1] )
+			return false;
+
+	return true;
+}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+template < class SymbolType, class StateType >
+std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > Run::calculateState ( const automaton::InputDrivenDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	StateType state = automaton.getInitialState ( );
+	std::deque < SymbolType > pushdownStore {
+		automaton.getInitialSymbol ( )
+	};
+	unsigned i = 0;
+	std::set < unsigned > occ;
+	bool res = true;
+
+	if ( automaton.getFinalStates ( ).count ( state ) )
+		occ.insert ( i );
+
+	if ( common::GlobalData::verbose )
+		std::clog << state << std::endl;
+
+	for ( const SymbolType & symbol : string.getContent ( ) ) {
+		auto transition = automaton.getTransitions ( ).find ( std::make_pair ( state, symbol ) );
+
+		if ( transition == automaton.getTransitions ( ).end ( ) ) {
+			res = false;
+			break;
+		}
+
+		const std::pair < std::vector < SymbolType >, std::vector < SymbolType > > & operation = automaton.getPushdownStoreOperations ( ).find ( symbol )->second;
+
+		if ( !canPop ( pushdownStore, operation.first ) ) {
+			res = false;
+			break;
+		}
+
+		for ( unsigned j = 0; j < operation.first.size ( ); j++ ) pushdownStore.pop_back ( );
+
+		for ( const auto & push : std::make_reverse ( operation.second ) ) pushdownStore.push_back ( push );
+
+		state = transition->second;
+		i++;
+
+		if ( automaton.getFinalStates ( ).count ( state ) )
+			occ.insert ( i );
+
+		if ( common::GlobalData::verbose )
+			std::clog << state << std::endl;
+	}
+
+	return std::make_tuple ( res, state, occ, pushdownStore );
+}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+template < class SymbolType, class StateType >
+std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > Run::calculateState ( const automaton::VisiblyPushdownDPDA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	StateType state = automaton.getInitialState ( );
+	std::deque < SymbolType > pushdownStore {
+		automaton.getBottomOfTheStackSymbol ( )
+	};
+	unsigned i = 0;
+	std::set < unsigned > occ;
+	bool res = true;
+
+	if ( automaton.getFinalStates ( ).count ( state ) )
+		occ.insert ( i );
+
+	if ( common::GlobalData::verbose )
+		std::clog << state << std::endl;
+
+	for ( const SymbolType & symbol : string.getContent ( ) ) {
+		if ( automaton.getCallInputAlphabet ( ).count ( symbol ) ) {
+			auto transition = automaton.getCallTransitions ( ).find ( std::make_pair ( state, symbol ) );
+
+			if ( transition == automaton.getCallTransitions ( ).end ( ) ) {
+				res = false;
+				break;
+			}
+
+			pushdownStore.push_back ( transition->second.second );
+			state = transition->second.first;
+		} else if ( automaton.getReturnInputAlphabet ( ).count ( symbol ) ) {
+			auto transition = automaton.getReturnTransitions ( ).find ( std::make_tuple ( state, symbol, pushdownStore.back ( ) ) );
+
+			if ( transition == automaton.getReturnTransitions ( ).end ( ) ) {
+				res = false;
+				break;
+			}
+
+			if ( pushdownStore.back ( ) != automaton.getBottomOfTheStackSymbol ( ) ) pushdownStore.pop_back ( );
+
+			state = transition->second;
+		} else if ( automaton.getLocalInputAlphabet ( ).count ( symbol ) ) {
+			auto transition = automaton.getLocalTransitions ( ).find ( std::make_pair ( state, symbol ) );
+
+			if ( transition == automaton.getLocalTransitions ( ).end ( ) ) {
+				res = false;
+				break;
+			}
+
+			state = transition->second;
+		} else {
+			res = false;
+			break;
+		}
+
+		i++;
+
+		if ( automaton.getFinalStates ( ).count ( state ) )
+			occ.insert ( i );
+
+		if ( common::GlobalData::verbose )
+			std::clog << state << std::endl;
+	}
+
+	return std::make_tuple ( res, state, occ, pushdownStore );
+}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+template < class SymbolType, class EpsilonType, class StateType >
+std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > Run::calculateState ( const automaton::RealTimeHeightDeterministicDPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	StateType state = automaton.getInitialState ( );
+	std::deque < SymbolType > pushdownStore {
+		automaton.getBottomOfTheStackSymbol ( )
+	};
+	unsigned i = 0;
+	std::set < unsigned > occ;
+	bool res = true;
+
+	if ( automaton.getFinalStates ( ).count ( state ) )
+		occ.insert ( i );
+
+	if ( common::GlobalData::verbose )
+		std::clog << state << std::endl;
+
+	for ( auto symbolIter = string.getContent ( ).begin ( ); symbolIter != string.getContent ( ).end ( ); ) {
+
+		auto callTransition = automaton.getCallTransitions ( ).find ( std::make_pair ( state, * symbolIter ) );
+
+		if ( callTransition != automaton.getCallTransitions ( ).end ( ) ) {
+			symbolIter++;
+			i++;
+		} else {
+			callTransition = automaton.getCallTransitions ( ).find ( std::make_pair ( state, EpsilonType ( ) ) );
+		}
+
+		if ( callTransition != automaton.getCallTransitions ( ).end ( ) ) {
+			pushdownStore.push_back ( callTransition->second.second );
+			state = callTransition->second.first;
+		} else {
+			res = false;
+		}
+
+		if ( !res ) {
+			auto returnTransition = automaton.getReturnTransitions ( ).find ( std::make_tuple ( state, * symbolIter, pushdownStore.back ( ) ) );
+
+			if ( returnTransition != automaton.getReturnTransitions ( ).end ( ) ) {
+				symbolIter++;
+				i++;
+			} else {
+				returnTransition = automaton.getReturnTransitions ( ).find ( std::make_tuple ( state, EpsilonType ( ), pushdownStore.back ( ) ) );
+			}
+
+			if ( returnTransition != automaton.getReturnTransitions ( ).end ( ) ) {
+				pushdownStore.pop_back ( );
+				state = returnTransition->second;
+			} else {
+				res = false;
+			}
+		}
+
+		if ( !res ) {
+			auto localTransition = automaton.getLocalTransitions ( ).find ( std::make_pair ( state, * symbolIter ) );
+
+			if ( localTransition != automaton.getLocalTransitions ( ).end ( ) ) {
+				symbolIter++;
+				i++;
+			} else {
+				localTransition = automaton.getLocalTransitions ( ).find ( std::make_pair ( state, EpsilonType ( ) ) );
+			}
+
+			if ( localTransition != automaton.getLocalTransitions ( ).end ( ) )
+				state = localTransition->second;
+			else
+				res = false;
+		}
+
+		if ( automaton.getFinalStates ( ).count ( state ) )
+			occ.insert ( i );
+
+		if ( common::GlobalData::verbose )
+			std::clog << state << std::endl;
+
+		if ( res == false )
+			break;
+	}
+
+	return std::make_tuple ( res, state, occ, pushdownStore );
+}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+template < class SymbolType, class EpsilonType, class StateType >
+std::tuple < bool, StateType, std::set < unsigned >, std::deque < SymbolType > > Run::calculateState ( const automaton::DPDA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	StateType state = automaton.getInitialState ( );
+	std::deque < SymbolType > pushdownStore {
+		automaton.getInitialSymbol ( )
+	};
+	unsigned i = 0;
+	std::set < unsigned > occ;
+	bool res = true;
+
+	if ( automaton.getFinalStates ( ).count ( state ) )
+		occ.insert ( i );
+
+	if ( common::GlobalData::verbose ) {
+		std::clog << "State : " << state << std::endl;
+		std::clog << "PushdownStore : " << pushdownStore << std::endl;
+	}
+
+	for ( auto symbolIter = string.getContent ( ).begin ( ); symbolIter != string.getContent ( ).end ( ); ) {
+		auto transitions = automaton.getTransitionsFromState ( state );
+		auto transition	 = transitions.begin ( );
+
+		for ( ; transition != transitions.end ( ); transition++ ) {
+			if ( ( std::get < 1 > ( transition->first ) != * symbolIter ) && !std::get < 1 > ( transition->first ).template is < EpsilonType > ( ) ) continue;
+
+			if ( canPop ( pushdownStore, std::get < 2 > ( transition->first ) ) ) break;
+		}
+
+		if ( transition == transitions.end ( ) ) {
+			res = false;
+			break;
+		}
+
+		if ( common::GlobalData::verbose )
+			std::clog << "Transition: " << * transition << std::endl;
+
+		for ( unsigned j = 0; j < std::get < 2 > ( transition->first ).size ( ); j++ ) pushdownStore.pop_back ( );
+
+		for ( const auto & symbol : std::make_reverse ( transition->second.second ) ) pushdownStore.push_back ( symbol );
+
+		state = transition->second.first;
+
+		if ( !std::get < 1 > ( transition->first ).template is < EpsilonType > ( ) ) {
+			i++;
+			symbolIter++;
+		}
+
+		if ( automaton.getFinalStates ( ).count ( state ) )
+			occ.insert ( i );
+
+		if ( common::GlobalData::verbose ) {
+			std::clog << "State: " << state << std::endl;
+			std::clog << "PushdownStore: " << pushdownStore << std::endl;
+		}
+	}
+
+	return std::make_tuple ( res, state, occ, pushdownStore );
+}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+template < class SymbolType >
+struct graphStructuredStack {
+	graphStructuredStack ( std::shared_ptr < graphStructuredStack < SymbolType > > parent, SymbolType data ) : m_parent(parent), m_data(data) {}
+	std::shared_ptr < graphStructuredStack < SymbolType > > m_parent;
+	SymbolType m_data;
+};
+
+template < class SymbolType, class EpsilonType, class StateType >
+std::tuple < bool, std::set < StateType >, std::set < std::vector < SymbolType > > > Run::calculateStates ( const automaton::NPDTA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	bool res = false;
+	unsigned i = 0;
+	std::set < unsigned > occurrences;
+	StateType state = automaton . getInitialState ();
+	typename std::vector<SymbolType>::const_iterator symbolIter = string . getContent () . begin ();
+	std::shared_ptr < graphStructuredStack < SymbolType > > stackNode = std::make_shared < graphStructuredStack < SymbolType > > ( nullptr, * symbolIter );
+	std::shared_ptr < graphStructuredStack < SymbolType > > outputNode = std::make_shared < graphStructuredStack < SymbolType > > ( nullptr, * symbolIter );
+
+	if ( automaton . getFinalStates () . count ( state ) ) {
+		occurrences . insert ( i );
+	}
+
+	std::deque < std::tuple < StateType, typename std::vector<SymbolType>::const_iterator, std::shared_ptr < graphStructuredStack < SymbolType > >, std::shared_ptr < graphStructuredStack < SymbolType > > > > bftQueue;
+	auto configuration = std::make_tuple ( state, symbolIter, stackNode, outputNode );
+	bftQueue . push_back ( configuration );
+
+	std::set < std::vector < SymbolType > > allOutputs;
+	std::set < StateType > states;
+
+	while ( ! bftQueue . empty () ) {
+		configuration = bftQueue . front (); bftQueue . pop_front ();
+		state = std::get<0>(configuration);
+		symbolIter = std::get<1>(configuration);
+		stackNode = std::get<2>(configuration);
+		outputNode = std::get<3>(configuration);
+
+		if ( symbolIter == string . getContent () . end () ) {
+			states . insert ( state );
+			if ( automaton . getFinalStates () . count ( state ) && stackNode -> m_parent == NULL ) {
+				res = true;
+				std::vector < SymbolType > output;
+				while ( outputNode->m_parent != NULL ) {
+					output . push_back ( outputNode->m_data );
+					outputNode = outputNode -> m_parent;
+				}
+				std::reverse ( output.begin(), output.end() );
+				allOutputs . insert ( output );
+			}
+			continue;
+		}
+
+		for ( const auto & transition : automaton . getTransitionsFromState ( state ) ) {
+			if ( std::get<1>(transition . first) != * symbolIter && ! std::get<1>(transition . first) . template is < EpsilonType >() )
+				continue;
+
+			const auto & pop = std::get<2>(transition . first);
+			std::shared_ptr < graphStructuredStack < SymbolType > > stackNodeCopy = stackNode;
+			std::shared_ptr < graphStructuredStack < SymbolType > > outputNodeCopy = outputNode;
+
+			unsigned j = 0;
+			for ( ; j < pop . size (); j ++ ) {
+				if ( stackNodeCopy->m_parent == NULL || stackNodeCopy->m_data != pop . at (j) ) {
+					break;
+				}
+				stackNodeCopy = stackNodeCopy -> m_parent;
+			}
+			if ( j == pop . size () ) {
+				for ( const auto & elem : std::make_reverse ( std::get<1>(transition . second ) ) ) {
+					stackNodeCopy = std::make_shared < graphStructuredStack < SymbolType > > ( stackNodeCopy, elem );
+				}
+				for ( const auto & elem : std::get<2>(transition . second) ) {
+					outputNodeCopy = std::make_shared < graphStructuredStack < SymbolType > > ( outputNodeCopy, elem );
+				}
+
+				if ( ! std::get<1>(transition . first) . template is< EpsilonType > ( ) ) {
+					configuration = std::make_tuple ( std::get<0>(transition . second), symbolIter + 1, stackNodeCopy, outputNodeCopy );
+				} else {
+					configuration = std::make_tuple ( std::get<0>(transition . second), symbolIter, stackNodeCopy, outputNodeCopy );
+				}
+				bftQueue . push_back ( configuration );
+			} else {
+				states . insert ( state );
+			}
+		}
+	}
+
+	return std::make_tuple ( res, states, allOutputs );
+}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
 } /* namespace run */
 
 } /* namespace automaton */
diff --git a/alib2algo/src/automaton/run/Translate.cpp b/alib2algo/src/automaton/run/Translate.cpp
index ff715de363..fb1bebc5c3 100644
--- a/alib2algo/src/automaton/run/Translate.cpp
+++ b/alib2algo/src/automaton/run/Translate.cpp
@@ -6,11 +6,6 @@
  */
 
 #include "Translate.h"
-#include "Run.h"
-#include <automaton/PDA/NPDTA.h>
-
-#include <deque>
-#include <set>
 
 namespace automaton {
 
@@ -24,16 +19,6 @@ std::set < string::LinearString < > > Translate::translate ( const automaton::Au
 	return dispatch ( automaton.getData ( ), string );
 }
 
-std::set < string::LinearString < > > Translate::translate ( const automaton::NPDTA < > & automaton, const string::LinearString < > & string ) {
-	std::tuple < bool, std::set < label::Label >, std::set < std::vector < alphabet::Symbol > > > res = Run::calculateStates ( automaton, string );
-	std::set < string::LinearString < > > strings;
-	for ( auto iter = std::get<2>(res).begin(); iter != std::get<2>(res).end(); iter ++ ) {
-		string::LinearString < > str (* iter);
-		strings . insert ( str );
-	}
-	return strings;
-}
-
 auto TranslateNPDTALinearString = Translate::RegistratorWrapper < std::set < string::LinearString < > >, automaton::NPDTA < >, string::LinearString < > > ( Translate::translate );
 
 } /* namespace run */
diff --git a/alib2algo/src/automaton/run/Translate.h b/alib2algo/src/automaton/run/Translate.h
index fb4db98e17..aa3604fc30 100644
--- a/alib2algo/src/automaton/run/Translate.h
+++ b/alib2algo/src/automaton/run/Translate.h
@@ -15,6 +15,12 @@
 #include <string/LinearString.h>
 #include <alphabet/Symbol.h>
 
+#include "Run.h"
+#include <automaton/PDA/NPDTA.h>
+
+#include <deque>
+#include <set>
+
 namespace automaton {
 
 namespace run {
@@ -28,10 +34,22 @@ public:
 	static std::set < string::LinearString < > > translate ( const automaton::Automaton & automaton, const alib::Object & object );
 	static std::set < string::LinearString < > > translate ( const automaton::Automaton & automaton, const string::LinearString < > & string );
 
-	static std::set < string::LinearString < > > translate ( const automaton::NPDTA < > & automaton, const string::LinearString < > & string );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static std::set < string::LinearString < SymbolType > > translate ( const automaton::NPDTA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string );
 
 };
 
+template < class SymbolType, class EpsilonType, class StateType >
+std::set < string::LinearString < SymbolType > > Translate::translate ( const automaton::NPDTA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	std::tuple < bool, std::set < StateType >, std::set < std::vector < SymbolType > > > res = Run::calculateStates ( automaton, string );
+	std::set < string::LinearString < SymbolType > > strings;
+	for ( auto iter = std::get<2>(res).begin(); iter != std::get<2>(res).end(); iter ++ ) {
+		string::LinearString < SymbolType > str (* iter);
+		strings . insert ( str );
+	}
+	return strings;
+}
+
 } /* namespace run */
 
 } /* namespace automaton */
-- 
GitLab