diff --git a/acompare2/src/AutomatonCompare.cpp b/acompare2/src/AutomatonCompare.cpp
index 31dea9dd3906b86a0e8c33de600fda308a3a07d2..9bb5413b032ffff87a381ee2e9dfaa5fc76750ea 100644
--- a/acompare2/src/AutomatonCompare.cpp
+++ b/acompare2/src/AutomatonCompare.cpp
@@ -62,7 +62,7 @@ bool AutomatonCompare::testCompare(const automaton::NFA < > & a, const automaton
 			a.getTransitions()    == b.getTransitions()    ;
 }
 
-bool AutomatonCompare::testCompare(const automaton::EpsilonNFA& a, const automaton::EpsilonNFA& b) {
+bool AutomatonCompare::testCompare(const automaton::EpsilonNFA < > & a, const automaton::EpsilonNFA < > & b) {
 	return  	a.getFinalStates()    == b.getFinalStates()    &&
 			a.getInitialState()   == b.getInitialState()   &&
 //			a.getInputAlphabet()  == b.getInputAlphabet()  &&
@@ -378,7 +378,7 @@ void AutomatonCompare::printCompare(const automaton::NFA < > & a, const automato
 	}
 }
 
-void AutomatonCompare::printCompare(const automaton::EpsilonNFA& a, const automaton::EpsilonNFA& b) {
+void AutomatonCompare::printCompare(const automaton::EpsilonNFA < > & a, const automaton::EpsilonNFA < > & b) {
 	std::cout << "AutomatonCompareer" << std::endl;
 
 	if(a.getFinalStates() != b.getFinalStates()){
@@ -1205,7 +1205,7 @@ int AutomatonCompare::compare(const automaton::MultiInitialStateNFA < >& a, cons
 
 auto AutomatonCompareMultiInitialStateNFA = AutomatonCompare::RegistratorWrapper<int, automaton::MultiInitialStateNFA < >, automaton::MultiInitialStateNFA < >>(AutomatonCompare::compare);
 
-int AutomatonCompare::compare(const automaton::EpsilonNFA& a, const automaton::EpsilonNFA& b) {
+int AutomatonCompare::compare(const automaton::EpsilonNFA < > & a, const automaton::EpsilonNFA < > & b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
 	  return 1;
@@ -1214,7 +1214,7 @@ int AutomatonCompare::compare(const automaton::EpsilonNFA& a, const automaton::E
 	}
 }
 
-auto AutomatonCompareEpsilonNFA = AutomatonCompare::RegistratorWrapper<int, automaton::EpsilonNFA, automaton::EpsilonNFA>(AutomatonCompare::compare);
+auto AutomatonCompareEpsilonNFA = AutomatonCompare::RegistratorWrapper<int, automaton::EpsilonNFA < >, automaton::EpsilonNFA < > >(AutomatonCompare::compare);
 
 int AutomatonCompare::compare(const automaton::ExtendedNFA& a, const automaton::ExtendedNFA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
diff --git a/acompare2/src/AutomatonCompare.h b/acompare2/src/AutomatonCompare.h
index f2624bbf9cbfe398d4a152ea22f90bfcb0c81112..7b599e430d0d4a07cfecc3e63f633f68735eeac5 100644
--- a/acompare2/src/AutomatonCompare.h
+++ b/acompare2/src/AutomatonCompare.h
@@ -29,8 +29,8 @@ private:
 	static bool testCompare(const automaton::MultiInitialStateNFA < >& a, const automaton::MultiInitialStateNFA < >& b);
 	static void printCompare(const automaton::MultiInitialStateNFA < >& a, const automaton::MultiInitialStateNFA < >& b);
 
-	static bool testCompare(const automaton::EpsilonNFA& a, const automaton::EpsilonNFA& b);
-	static void printCompare(const automaton::EpsilonNFA& a, const automaton::EpsilonNFA& b);
+	static bool testCompare(const automaton::EpsilonNFA < > & a, const automaton::EpsilonNFA < > & b);
+	static void printCompare(const automaton::EpsilonNFA < > & a, const automaton::EpsilonNFA < > & b);
 
 	static bool testCompare(const automaton::ExtendedNFA& a, const automaton::ExtendedNFA& b);
 	static void printCompare(const automaton::ExtendedNFA& a, const automaton::ExtendedNFA& b);
@@ -84,7 +84,7 @@ public:
 	static int compare(const automaton::DFA<>& a, const automaton::DFA<>& b);
 	static int compare(const automaton::NFA < > & a, const automaton::NFA < > & b);
 	static int compare(const automaton::MultiInitialStateNFA < >& a, const automaton::MultiInitialStateNFA < >& b);
-	static int compare(const automaton::EpsilonNFA& a, const automaton::EpsilonNFA& b);
+	static int compare(const automaton::EpsilonNFA < > & a, const automaton::EpsilonNFA < > & b);
 	static int compare(const automaton::ExtendedNFA& a, const automaton::ExtendedNFA& b);
 	static int compare(const automaton::CompactNFA < > & a, const automaton::CompactNFA < > & b);
 
diff --git a/aconversions2/src/ConversionHandler.cpp b/aconversions2/src/ConversionHandler.cpp
index e25bcf2b6a618dc08d66064a4ab7e2e8ca777e48..8b5d3133d9ea318315addb3c7465674de1defa1d 100644
--- a/aconversions2/src/ConversionHandler.cpp
+++ b/aconversions2/src/ConversionHandler.cpp
@@ -189,7 +189,7 @@ void ConversionHandler::convertREtoFA ( void ) {
 	}
 
 	case THOMPSON_NFA: {
-		automaton::EpsilonNFA automaton = regexp::convert::ToAutomatonThompson::convert ( regexp );
+		automaton::EpsilonNFA < > automaton = regexp::convert::ToAutomatonThompson::convert ( regexp );
 
 		measurements::end ( );
 		measurements::start ( "Output write", measurements::Type::AUXILIARY );
diff --git a/aconvert2/src/DotConverter.cpp b/aconvert2/src/DotConverter.cpp
index b95e1569207e21e6e15f7058c77e90ea55e9b070..f3f5d3127b335fc1aef535a97f170159cd5f8114 100644
--- a/aconvert2/src/DotConverter.cpp
+++ b/aconvert2/src/DotConverter.cpp
@@ -50,7 +50,7 @@ void DotConverter::convert(std::ostream& out, const automaton::Automaton& a) {
 	dispatch(out, a.getData());
 }
 
-void DotConverter::convert(std::ostream& out, const automaton::EpsilonNFA& a) {
+void DotConverter::convert(std::ostream& out, const automaton::EpsilonNFA < > & a) {
 	out << "digraph automaton {\n";
 	out << "rankdir=LR;\n";
 	int cnt = 1;
@@ -81,7 +81,7 @@ void DotConverter::convert(std::ostream& out, const automaton::EpsilonNFA& a) {
 	out << "}";
 }
 
-auto DotConverterEpsilonNFA = DotConverter::RegistratorWrapper<void, automaton::EpsilonNFA>(DotConverter::convert);
+auto DotConverterEpsilonNFA = DotConverter::RegistratorWrapper<void, automaton::EpsilonNFA < > >(DotConverter::convert);
 
 void DotConverter::convert(std::ostream& out, const automaton::MultiInitialStateNFA < >& a) {
 	out << "digraph automaton {\n";
@@ -675,7 +675,7 @@ void DotConverter::convert(std::ostream& out, const automaton::OneTapeDTM<>& a)
 
 auto DotConverterOneTapeDTM = DotConverter::RegistratorWrapper<void, automaton::OneTapeDTM<>>(DotConverter::convert);
 
-void DotConverter::transitions(const automaton::EpsilonNFA& fsm, const std::map<label::Label, int>& states, std::ostream& out) {
+void DotConverter::transitions(const automaton::EpsilonNFA < > & fsm, const std::map<label::Label, int>& states, std::ostream& out) {
 	std::map<std::pair<int, int>, std::string> transitions;
 
 	//put transitions from automaton to "transitions"
diff --git a/aconvert2/src/DotConverter.h b/aconvert2/src/DotConverter.h
index acde01c9af23835c66a6e354303312e0e84e677a..e5fdcafe7fb0bb64212f6bd31fff516d1fbb2ff1 100644
--- a/aconvert2/src/DotConverter.h
+++ b/aconvert2/src/DotConverter.h
@@ -20,7 +20,7 @@
 #include <utility>
 
 class DotConverter : public std::SingleDispatchFirstStaticParam<DotConverter, void, std::ostream&, automaton::AutomatonBase> {
-	static void transitions(const automaton::EpsilonNFA& fsm, const std::map<label::Label, int>& states, std::ostream& out);
+	static void transitions(const automaton::EpsilonNFA < > & fsm, const std::map<label::Label, int>& states, std::ostream& out);
 	static void transitions(const automaton::MultiInitialStateNFA < >& fsm, const std::map<label::Label, int>& states, std::ostream& out);
 	static void transitions(const automaton::NFA < > & fsm, const std::map<label::Label, int>& states, std::ostream& out);
 	static void transitions(const automaton::DFA<>& fsm, const std::map<label::Label, int>& states, std::ostream& out);
@@ -42,7 +42,7 @@ class DotConverter : public std::SingleDispatchFirstStaticParam<DotConverter, vo
 public:
 	static void convert(std::ostream& out, const automaton::Automaton& a);
 
-	static void convert(std::ostream& out, const automaton::EpsilonNFA& a);
+	static void convert(std::ostream& out, const automaton::EpsilonNFA < > & a);
 	static void convert(std::ostream& out, const automaton::MultiInitialStateNFA < >& a);
 	static void convert(std::ostream& out, const automaton::NFA < > & a);
 	static void convert(std::ostream& out, const automaton::DFA<>& a);
diff --git a/aconvert2/src/GasTexConverter.cpp b/aconvert2/src/GasTexConverter.cpp
index 78d59dab8ed4f6e0b5083338c52b202b159445b0..171da4461f630abcc698287b9c76468656fa526f 100644
--- a/aconvert2/src/GasTexConverter.cpp
+++ b/aconvert2/src/GasTexConverter.cpp
@@ -38,7 +38,7 @@ void GasTexConverter::convert(std::ostream& out, const automaton::Automaton& a)
 	dispatch(out, a.getData());
 }
 
-void GasTexConverter::convert(std::ostream& out, const automaton::EpsilonNFA& a) {
+void GasTexConverter::convert(std::ostream& out, const automaton::EpsilonNFA < > & a) {
 	out << "\\begin{center}\n";
 	out << "\\begin{picture}(,)(,)\n";
 
@@ -77,7 +77,7 @@ void GasTexConverter::convert(std::ostream& out, const automaton::EpsilonNFA& a)
 	out << "\\end{picture}\n";
 }
 
-auto GasTexConverterEpsilonNFA = GasTexConverter::RegistratorWrapper<void, automaton::EpsilonNFA>(GasTexConverter::convert);
+auto GasTexConverterEpsilonNFA = GasTexConverter::RegistratorWrapper<void, automaton::EpsilonNFA < > >(GasTexConverter::convert);
 
 void GasTexConverter::convert(std::ostream& out, const automaton::MultiInitialStateNFA < >& a) {
 	out << "\\begin{center}\n";
@@ -788,7 +788,7 @@ void GasTexConverter::printTransitionMap(const std::map<std::pair<std::string, s
 	}
 }
 
-void GasTexConverter::transitions(const automaton::EpsilonNFA& fsm, std::ostream& out) {
+void GasTexConverter::transitions(const automaton::EpsilonNFA < > & fsm, std::ostream& out) {
 	std::map<std::pair<std::string, std::string>, std::string> transitionMap;
 	for (const auto& transition : fsm.getTransitions()) {
 		for(const auto& to : transition.second) {
diff --git a/aconvert2/src/GasTexConverter.h b/aconvert2/src/GasTexConverter.h
index eb71dd8621b18bf6f2f0520ca2912c3dda7662af..f69614fff6a9ca1233f66335c8907805e461c390 100644
--- a/aconvert2/src/GasTexConverter.h
+++ b/aconvert2/src/GasTexConverter.h
@@ -21,7 +21,7 @@ class GasTexConverter : public std::SingleDispatchFirstStaticParam<GasTexConvert
 	static void printTransitionMap( const std::map<std::pair<std::string, std::string>, std::string> transitionMap, std::ostream& out);
 	static std::string getStackSymbols(const std::vector<alphabet::Symbol>& stackSymbols);
 
-	static void transitions(const automaton::EpsilonNFA& fsm, std::ostream& out);
+	static void transitions(const automaton::EpsilonNFA < > & fsm, std::ostream& out);
 	static void transitions(const automaton::MultiInitialStateNFA < >& fsm, std::ostream& out);
 	static void transitions(const automaton::NFA < > & fsm, std::ostream& out);
 	static void transitions(const automaton::DFA<>& fsm, std::ostream& out);
@@ -43,7 +43,7 @@ class GasTexConverter : public std::SingleDispatchFirstStaticParam<GasTexConvert
 public:
 	static void convert(std::ostream& out, const automaton::Automaton& a);
 
-	static void convert(std::ostream& out, const automaton::EpsilonNFA& a);
+	static void convert(std::ostream& out, const automaton::EpsilonNFA < > & a);
 	static void convert(std::ostream& out, const automaton::MultiInitialStateNFA < >& a);
 	static void convert(std::ostream& out, const automaton::NFA < > & a);
 	static void convert(std::ostream& out, const automaton::DFA<>& a);
diff --git a/aconvert2/src/TikZConverter.cpp b/aconvert2/src/TikZConverter.cpp
index 92892a503954871a16e3882e95f6a3e8203aee11..7fe94c188f54ae14c79e41cc12178d1027da5e1e 100644
--- a/aconvert2/src/TikZConverter.cpp
+++ b/aconvert2/src/TikZConverter.cpp
@@ -51,7 +51,7 @@ void TikZConverter::convert ( std::ostream & out, const automaton::Automaton & a
 	dispatch ( out, a.getData ( ) );
 }
 
-void TikZConverter::convert ( std::ostream & out, const automaton::EpsilonNFA & a ) {
+void TikZConverter::convert ( std::ostream & out, const automaton::EpsilonNFA < > & a ) {
 	out << "\\begin{tikzpicture}\n";
 	int cnt = 1;
 
@@ -78,7 +78,7 @@ void TikZConverter::convert ( std::ostream & out, const automaton::EpsilonNFA &
 	out << "\\end{tikzpicture}";
 }
 
-auto TikZConverterEpsilonNFA = TikZConverter::RegistratorWrapper < void, automaton::EpsilonNFA > ( TikZConverter::convert );
+auto TikZConverterEpsilonNFA = TikZConverter::RegistratorWrapper < void, automaton::EpsilonNFA < > > ( TikZConverter::convert );
 
 void TikZConverter::convert ( std::ostream & out, const automaton::MultiInitialStateNFA < > & a ) {
 	out << "\\begin{tikzpicture}\n";
@@ -596,7 +596,7 @@ void TikZConverter::convert ( std::ostream & out, const automaton::OneTapeDTM <
 
 auto TikZConverterOneTapeDTM = TikZConverter::RegistratorWrapper < void, automaton::OneTapeDTM < > > ( TikZConverter::convert );
 
-void TikZConverter::transitions ( const automaton::EpsilonNFA & fsm, const std::map < label::Label, int > & states, std::ostream & out ) {
+void TikZConverter::transitions ( const automaton::EpsilonNFA < > & fsm, const std::map < label::Label, int > & states, std::ostream & out ) {
 	std::map < std::pair < int, int >, std::string > transitions;
 
 	 // put transitions from automaton to "transitions"
diff --git a/aconvert2/src/TikZConverter.h b/aconvert2/src/TikZConverter.h
index 815504a9cba1048a2b3f169b0a5bf6a02c13675f..3773b21e0261fc78afc63a3148d4e2a5f1e0d1be 100644
--- a/aconvert2/src/TikZConverter.h
+++ b/aconvert2/src/TikZConverter.h
@@ -20,7 +20,7 @@
 #include <utility>
 
 class TikZConverter : public std::SingleDispatchFirstStaticParam < TikZConverter, void, std::ostream &, automaton::AutomatonBase > {
-	static void transitions ( const automaton::EpsilonNFA & fsm, const std::map < label::Label, int > & states, std::ostream & out );
+	static void transitions ( const automaton::EpsilonNFA < > & fsm, const std::map < label::Label, int > & states, std::ostream & out );
 	static void transitions ( const automaton::MultiInitialStateNFA < > & fsm, const std::map < label::Label, int > & states, std::ostream & out );
 	static void transitions ( const automaton::NFA < > & fsm, const std::map < label::Label, int > & states, std::ostream & out );
 	static void transitions ( const automaton::DFA<> & fsm, const std::map < label::Label, int > & states, std::ostream & out );
@@ -43,7 +43,7 @@ class TikZConverter : public std::SingleDispatchFirstStaticParam < TikZConverter
 public:
 	static void convert ( std::ostream & out, const automaton::Automaton & a );
 
-	static void convert ( std::ostream & out, const automaton::EpsilonNFA & a );
+	static void convert ( std::ostream & out, const automaton::EpsilonNFA < > & a );
 	static void convert ( std::ostream & out, const automaton::MultiInitialStateNFA < > & a );
 	static void convert ( std::ostream & out, const automaton::NFA < > & a );
 	static void convert ( std::ostream & out, const automaton::DFA<> & a );
diff --git a/alib2algo/src/automaton/convert/ToRegExp.cpp b/alib2algo/src/automaton/convert/ToRegExp.cpp
index c4d0e0c5cd593c42564653a0a8ad6c77098a0f5d..549048bca0c43a462fd1db22ec0c39d3b457d00e 100644
--- a/alib2algo/src/automaton/convert/ToRegExp.cpp
+++ b/alib2algo/src/automaton/convert/ToRegExp.cpp
@@ -16,11 +16,11 @@ regexp::RegExp ToRegExp::convert(const automaton::Automaton& automaton) {
 	return dispatch(automaton.getData());
 }
 
-regexp::RegExp ToRegExp::convert(const automaton::EpsilonNFA& automaton) {
+regexp::RegExp ToRegExp::convert(const automaton::EpsilonNFA < > & automaton) {
 	return regexp::RegExp(ToRegExpStateElimination::convert(automaton));
 }
 
-auto ToRegExpEpsilonNFA = ToRegExp::RegistratorWrapper<regexp::RegExp, automaton::EpsilonNFA>(ToRegExp::convert);
+auto ToRegExpEpsilonNFA = ToRegExp::RegistratorWrapper<regexp::RegExp, automaton::EpsilonNFA < > >(ToRegExp::convert);
 
 regexp::RegExp ToRegExp::convert(const automaton::MultiInitialStateNFA < > & automaton) {
 	return regexp::RegExp(ToRegExpStateElimination::convert(automaton));
diff --git a/alib2algo/src/automaton/convert/ToRegExp.h b/alib2algo/src/automaton/convert/ToRegExp.h
index cbf67d5b9925d6b5ff19a85f00db811692f2f708..3a26dad971a4927fac9097d3c606e602aa2859b1 100644
--- a/alib2algo/src/automaton/convert/ToRegExp.h
+++ b/alib2algo/src/automaton/convert/ToRegExp.h
@@ -31,7 +31,7 @@ public:
 	 */
 	static regexp::RegExp convert(const automaton::Automaton& automaton);
 
-	static regexp::RegExp convert(const automaton::EpsilonNFA& automaton);
+	static regexp::RegExp convert(const automaton::EpsilonNFA < > & automaton);
 	static regexp::RegExp convert(const automaton::MultiInitialStateNFA < > & automaton);
 	static regexp::RegExp convert(const automaton::NFA<>& automaton);
 	static regexp::RegExp convert(const automaton::DFA<>& automaton);
diff --git a/alib2algo/src/automaton/convert/ToRegExpAlgebraic.cpp b/alib2algo/src/automaton/convert/ToRegExpAlgebraic.cpp
index a9ccfe104293800c0121771b9067b5ceb3d915ea..a2306259faafee6843e89c897de84864a53c3212 100644
--- a/alib2algo/src/automaton/convert/ToRegExpAlgebraic.cpp
+++ b/alib2algo/src/automaton/convert/ToRegExpAlgebraic.cpp
@@ -26,7 +26,7 @@ regexp::RegExp ToRegExpAlgebraic::convert(const automaton::Automaton& automaton)
 	return dispatch(automaton.getData());
 }
 
-regexp::UnboundedRegExp ToRegExpAlgebraic::convert( const automaton::EpsilonNFA & automaton ) {
+regexp::UnboundedRegExp ToRegExpAlgebraic::convert( const automaton::EpsilonNFA < > & automaton ) {
 	equations::RightRegularEquationSolver solver;
 
 	// initialize equations
@@ -53,7 +53,7 @@ regexp::UnboundedRegExp ToRegExpAlgebraic::convert( const automaton::EpsilonNFA
 	return solver.solve( alphabet::Symbol( alphabet::LabeledSymbol (automaton.getInitialState() ) ) );
 }
 
-auto ToRegExpAlgebraicEpsilonNFA = ToRegExpAlgebraic::RegistratorWrapper<regexp::UnboundedRegExp, automaton::EpsilonNFA>(ToRegExpAlgebraic::convert);
+auto ToRegExpAlgebraicEpsilonNFA = ToRegExpAlgebraic::RegistratorWrapper<regexp::UnboundedRegExp, automaton::EpsilonNFA < > >(ToRegExpAlgebraic::convert);
 
 regexp::UnboundedRegExp ToRegExpAlgebraic::convert( const automaton::MultiInitialStateNFA < > & automaton ) {
 	equations::RightRegularEquationSolver solver;
diff --git a/alib2algo/src/automaton/convert/ToRegExpAlgebraic.h b/alib2algo/src/automaton/convert/ToRegExpAlgebraic.h
index c29dfb44ef916d900f83e779b1c9857bfc1c82d8..824c222189ef7944ff06e180bfa7b268570d7ed4 100644
--- a/alib2algo/src/automaton/convert/ToRegExpAlgebraic.h
+++ b/alib2algo/src/automaton/convert/ToRegExpAlgebraic.h
@@ -38,7 +38,7 @@ public:
 	 */
 	static regexp::RegExp convert(const automaton::Automaton& automaton);
 
-	static regexp::UnboundedRegExp convert(const automaton::EpsilonNFA& automaton);
+	static regexp::UnboundedRegExp convert(const automaton::EpsilonNFA < > & automaton);
 	static regexp::UnboundedRegExp convert(const automaton::MultiInitialStateNFA < > & automaton);
 	static regexp::UnboundedRegExp convert(const automaton::NFA < > & automaton);
 	static regexp::UnboundedRegExp convert(const automaton::DFA<>& automaton);
diff --git a/alib2algo/src/automaton/convert/ToRegExpStateElimination.cpp b/alib2algo/src/automaton/convert/ToRegExpStateElimination.cpp
index 66298ea6b7c486130293a6e05f6c7c5ece55504d..be91b71206f6ad55c4a713de40cde72db3f63531 100644
--- a/alib2algo/src/automaton/convert/ToRegExpStateElimination.cpp
+++ b/alib2algo/src/automaton/convert/ToRegExpStateElimination.cpp
@@ -46,7 +46,7 @@ regexp::RegExp ToRegExpStateElimination::convert(const T& automaton) {
 				regexp::RegExpIterate::iterate(transition(extendedAutomaton, *extendedAutomaton.getFinalStates().begin(), *extendedAutomaton.getFinalStates().begin()))));
 }
 
-auto ToRegExpStateEliminationEpsilonNFA = ToRegExpStateElimination::RegistratorWrapper<regexp::RegExp, automaton::EpsilonNFA>(ToRegExpStateElimination::convert);
+auto ToRegExpStateEliminationEpsilonNFA = ToRegExpStateElimination::RegistratorWrapper<regexp::RegExp, automaton::EpsilonNFA < > >(ToRegExpStateElimination::convert);
 auto ToRegExpStateEliminationMultiInitialStateNFA = ToRegExpStateElimination::RegistratorWrapper<regexp::RegExp, automaton::MultiInitialStateNFA < > >(ToRegExpStateElimination::convert);
 auto ToRegExpStateEliminationNFA = ToRegExpStateElimination::RegistratorWrapper<regexp::RegExp, automaton::NFA < > >(ToRegExpStateElimination::convert);
 auto ToRegExpStateEliminationDFA = ToRegExpStateElimination::RegistratorWrapper<regexp::RegExp, automaton::DFA<>>(ToRegExpStateElimination::convert);
diff --git a/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp b/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp
index 0660fa8a79272b6c59d37e9acde4b6b63ef07f0e..cbd5eee23536bb5afd44376825c950aad4ef01cd 100644
--- a/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp
+++ b/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp
@@ -26,7 +26,7 @@ namespace automaton {
 
 namespace properties {
 
-std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::EpsilonNFA & fsm) {
+std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::EpsilonNFA < > & fsm) {
 	std::deque<std::map<label::Label, std::set<label::Label>>> Qi;
 
 	Qi.push_back({});
@@ -52,7 +52,7 @@ std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClos
 	return Qi.at(i);
 }
 
-auto AllEpsilonClosureEpsilonNFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::EpsilonNFA>(AllEpsilonClosure::allEpsilonClosure);
+auto AllEpsilonClosureEpsilonNFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::EpsilonNFA < > >(AllEpsilonClosure::allEpsilonClosure);
 
 std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::MultiInitialStateNFA < > & fsm) {
 	std::map<label::Label, std::set<label::Label>> closure;
diff --git a/alib2algo/src/automaton/properties/AllEpsilonClosure.h b/alib2algo/src/automaton/properties/AllEpsilonClosure.h
index 3e5f327d9b6313aa421ed06cbb894ae0c62dad53..9bd386383a6c9bf4baba230e243f781a7da9960d 100644
--- a/alib2algo/src/automaton/properties/AllEpsilonClosure.h
+++ b/alib2algo/src/automaton/properties/AllEpsilonClosure.h
@@ -27,7 +27,7 @@ public:
 	/**
 	 * Computes allEpsilon closure of a state in allEpsilon nonfree automaton
 	 */
-	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::EpsilonNFA & fsm);
+	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::EpsilonNFA < > & fsm);
 	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::MultiInitialStateNFA < > & fsm);
 	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::NFA < > & fsm);
 	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::DFA < > & fsm);
diff --git a/alib2algo/src/automaton/properties/EpsilonClosure.cpp b/alib2algo/src/automaton/properties/EpsilonClosure.cpp
index 943713766d9d10968e40578861e99e2e7c943e63..2c1538d3e44b40fd3adacf9da8bf51a32faa211f 100644
--- a/alib2algo/src/automaton/properties/EpsilonClosure.cpp
+++ b/alib2algo/src/automaton/properties/EpsilonClosure.cpp
@@ -24,7 +24,7 @@ namespace automaton {
 
 namespace properties {
 
-std::set<label::Label> EpsilonClosure::epsilonClosure( const automaton::EpsilonNFA & fsm, const label::Label & q ) {
+std::set<label::Label> EpsilonClosure::epsilonClosure( const automaton::EpsilonNFA < > & fsm, const label::Label & q ) {
 	if(! fsm.getStates().count(q) ) throw exception::CommonException("State is not in the automaton");
 
 	std::set<label::Label> closure;
@@ -53,7 +53,7 @@ std::set<label::Label> EpsilonClosure::epsilonClosure( const automaton::EpsilonN
 	return closure;
 }
 
-auto EpsilonClosureEpsilonNFA = EpsilonClosure::RegistratorWrapper<std::set<label::Label>, automaton::EpsilonNFA>(EpsilonClosure::epsilonClosure);
+auto EpsilonClosureEpsilonNFA = EpsilonClosure::RegistratorWrapper<std::set<label::Label>, automaton::EpsilonNFA < > >(EpsilonClosure::epsilonClosure);
 
 std::set<label::Label> EpsilonClosure::epsilonClosure( const automaton::MultiInitialStateNFA < > & fsm, const label::Label & q ) {
 	if(! fsm.getStates().count(q) ) throw exception::CommonException("State is not in the automaton");
diff --git a/alib2algo/src/automaton/properties/EpsilonClosure.h b/alib2algo/src/automaton/properties/EpsilonClosure.h
index 648eedb49564dd45296a278487bf8e4b61628752..4c1b51b6e498ae5e2c88c1018392ac2c48280512 100644
--- a/alib2algo/src/automaton/properties/EpsilonClosure.h
+++ b/alib2algo/src/automaton/properties/EpsilonClosure.h
@@ -28,7 +28,7 @@ public:
 	/**
 	 * Computes epsilon closure of a state in epsilon nonfree automaton
 	 */
-	static std::set<label::Label> epsilonClosure( const automaton::EpsilonNFA & fsm, const label::Label & state );
+	static std::set<label::Label> epsilonClosure( const automaton::EpsilonNFA < > & fsm, const label::Label & state );
 	static std::set<label::Label> epsilonClosure( const automaton::MultiInitialStateNFA < > & fsm, const label::Label & state );
 	static std::set<label::Label> epsilonClosure( const automaton::NFA < > & fsm, const label::Label & state );
 	static std::set<label::Label> epsilonClosure( const automaton::DFA < > & fsm, const label::Label & state );
diff --git a/alib2algo/src/automaton/properties/ReachableStates.cpp b/alib2algo/src/automaton/properties/ReachableStates.cpp
index 8f50bfa3633f212a31af5572c4bd17803d067386..029f340865321bc9c8296f10fb60fa863554e26e 100644
--- a/alib2algo/src/automaton/properties/ReachableStates.cpp
+++ b/alib2algo/src/automaton/properties/ReachableStates.cpp
@@ -51,7 +51,7 @@ std::set<label::Label> ReachableStates::reachableStates( const T & fsm ) {
 	return Qi.at( i );
 }
 
-auto ReachableStatesEpsilonNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::EpsilonNFA>(ReachableStates::reachableStates);
+auto ReachableStatesEpsilonNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::EpsilonNFA < > >(ReachableStates::reachableStates);
 auto ReachableStatesNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::NFA < > >(ReachableStates::reachableStates);
 auto ReachableStatesCompactNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::CompactNFA < > >(ReachableStates::reachableStates);
 auto ReachableStatesExtendedNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::ExtendedNFA>(ReachableStates::reachableStates);
diff --git a/alib2algo/src/automaton/properties/UsefullStates.cpp b/alib2algo/src/automaton/properties/UsefullStates.cpp
index 24383c62a2f695e9e14a4c1863f05b204e08aeba..1fd4061f41b10fb39b9ec87133cf3e428fc2c15c 100644
--- a/alib2algo/src/automaton/properties/UsefullStates.cpp
+++ b/alib2algo/src/automaton/properties/UsefullStates.cpp
@@ -49,7 +49,7 @@ std::set<label::Label> UsefullStates::usefullStates( const T & fsm ) {
 	return Qi.at( i );
 }
 
-auto UsefullStatesEpsilonNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::EpsilonNFA>(UsefullStates::usefullStates);
+auto UsefullStatesEpsilonNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::EpsilonNFA < > >(UsefullStates::usefullStates);
 auto UsefullStatesNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::NFA < > >(UsefullStates::usefullStates);
 auto UsefullStatesCompactNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::CompactNFA < > >(UsefullStates::usefullStates);
 auto UsefullStatesExtendedNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::ExtendedNFA>(UsefullStates::usefullStates);
diff --git a/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.cpp b/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.cpp
index 3fd7464cf704a70e12db7e6158df3f96f79ea7a2..2f5e29942017c0fe7fe9a310e0d0b30253c43597 100644
--- a/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.cpp
+++ b/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.cpp
@@ -31,7 +31,7 @@ automaton::NFA < > EpsilonRemoverIncoming::remove(const automaton::NFA < > & ori
 
 auto EpsilonRemoverIncomingNFA = EpsilonRemoverIncoming::RegistratorWrapper<automaton::NFA < > , automaton::NFA < > >(EpsilonRemoverIncoming::remove);
 
-automaton::NFA < > EpsilonRemoverIncoming::remove( const automaton::EpsilonNFA & origFSM ) {
+automaton::NFA < > EpsilonRemoverIncoming::remove( const automaton::EpsilonNFA < > & origFSM ) {
 	automaton::NFA < > fsm(origFSM.getInitialState());
 
 	fsm.setStates( origFSM.getStates() );
@@ -69,7 +69,7 @@ automaton::NFA < > EpsilonRemoverIncoming::remove( const automaton::EpsilonNFA &
 	return fsm;
 }
 
-auto EpsilonRemoverIncomingEpsilonNFA = EpsilonRemoverIncoming::RegistratorWrapper<automaton::NFA < > , automaton::EpsilonNFA>(EpsilonRemoverIncoming::remove);
+auto EpsilonRemoverIncomingEpsilonNFA = EpsilonRemoverIncoming::RegistratorWrapper<automaton::NFA < > , automaton::EpsilonNFA < > >(EpsilonRemoverIncoming::remove);
 
 automaton::Automaton EpsilonRemoverIncoming::remove(const automaton::Automaton& automaton) {
 	return dispatch(automaton.getData());
diff --git a/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.h b/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.h
index eb185055e2a57d924cee3f6bc0cc1d0d95a82d29..a1373171435dd579dbcc7c903937df51b6446deb 100644
--- a/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.h
+++ b/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.h
@@ -27,7 +27,7 @@ public:
 	/**
 	 * Computes epsilon closure of a state in epsilon nonfree automaton
 	 */
-	static automaton::NFA < > remove( const automaton::EpsilonNFA & fsm );
+	static automaton::NFA < > remove( const automaton::EpsilonNFA < > & fsm );
 	static automaton::MultiInitialStateNFA < > remove( const automaton::MultiInitialStateNFA < > & fsm );
 	static automaton::NFA < > remove( const automaton::NFA < > & fsm );
 	static automaton::DFA<> remove( const automaton::DFA<> & fsm );
diff --git a/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.cpp b/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.cpp
index 78540e180bbc2a0c51310a103a027c290bc1d705..46f91072e4d8d6990d51f943d267faa553951c1f 100644
--- a/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.cpp
+++ b/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.cpp
@@ -31,7 +31,7 @@ automaton::NFA < > EpsilonRemoverOutgoing::remove(const automaton::NFA < > & ori
 
 auto EpsilonRemoverOutgoingNFA = EpsilonRemoverOutgoing::RegistratorWrapper<automaton::NFA < > , automaton::NFA < > >(EpsilonRemoverOutgoing::remove);
 
-automaton::MultiInitialStateNFA < > EpsilonRemoverOutgoing::remove( const automaton::EpsilonNFA & origFSM ) {
+automaton::MultiInitialStateNFA < > EpsilonRemoverOutgoing::remove( const automaton::EpsilonNFA < > & origFSM ) {
 	automaton::MultiInitialStateNFA < > fsm;
 	fsm.setStates( origFSM.getStates() );
 	fsm.setFinalStates( origFSM.getFinalStates() );
@@ -62,7 +62,7 @@ automaton::MultiInitialStateNFA < > EpsilonRemoverOutgoing::remove( const automa
 	return fsm;
 }
 
-auto EpsilonRemoverOutgoingEpsilonNFA = EpsilonRemoverOutgoing::RegistratorWrapper<automaton::MultiInitialStateNFA < > , automaton::EpsilonNFA>(EpsilonRemoverOutgoing::remove);
+auto EpsilonRemoverOutgoingEpsilonNFA = EpsilonRemoverOutgoing::RegistratorWrapper<automaton::MultiInitialStateNFA < > , automaton::EpsilonNFA < > >(EpsilonRemoverOutgoing::remove);
 
 automaton::Automaton EpsilonRemoverOutgoing::remove(const automaton::Automaton& automaton) {
 	return dispatch(automaton.getData());
diff --git a/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.h b/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.h
index 39659ac90b537595b25b7d4dacd7ba9382ce28cc..48abbc195fb902a91b57b602469be0bb7473b3c9 100644
--- a/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.h
+++ b/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.h
@@ -27,7 +27,7 @@ public:
 	/**
 	 * Computes epsilon closure of a state in epsilon nonfree automaton
 	 */
-	static automaton::MultiInitialStateNFA < > remove( const automaton::EpsilonNFA & fsm );
+	static automaton::MultiInitialStateNFA < > remove( const automaton::EpsilonNFA < > & fsm );
 	static automaton::MultiInitialStateNFA < > remove( const automaton::MultiInitialStateNFA < > & fsm );
 	static automaton::NFA < > remove( const automaton::NFA < > & fsm );
 	static automaton::DFA<> remove( const automaton::DFA<> & fsm );
diff --git a/alib2algo/src/automaton/simplify/SingleInitialState.cpp b/alib2algo/src/automaton/simplify/SingleInitialState.cpp
index a6b59c4932f27ed47ec856786f64382db3e88839..7cdf8e9b1d5826bab484ffc2957919bb9e14193f 100644
--- a/alib2algo/src/automaton/simplify/SingleInitialState.cpp
+++ b/alib2algo/src/automaton/simplify/SingleInitialState.cpp
@@ -71,11 +71,11 @@ automaton::DFA<> SingleInitialState::convert(const automaton::DFA<>& automaton)
 
 auto SingleInitialStateDFA = SingleInitialState::RegistratorWrapper<automaton::DFA<>, automaton::DFA<>>(SingleInitialState::convert);
 
-automaton::EpsilonNFA SingleInitialState::convert(const automaton::EpsilonNFA& automaton) {
+automaton::EpsilonNFA < > SingleInitialState::convert(const automaton::EpsilonNFA < > & automaton) {
 	return automaton;
 }
 
-auto SingleInitialStateEpsilonNFA = SingleInitialState::RegistratorWrapper<automaton::EpsilonNFA, automaton::EpsilonNFA>(SingleInitialState::convert);
+auto SingleInitialStateEpsilonNFA = SingleInitialState::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::EpsilonNFA < > >(SingleInitialState::convert);
 
 automaton::NFA < > SingleInitialState::convert(const automaton::NFA < > & automaton) {
 	return automaton;
diff --git a/alib2algo/src/automaton/simplify/SingleInitialState.h b/alib2algo/src/automaton/simplify/SingleInitialState.h
index 62659b8cdd48b3123dc1efec9f2755ba4f378ddc..be8f7382cb69961ea6f5bcba20f35aea6e6b302c 100644
--- a/alib2algo/src/automaton/simplify/SingleInitialState.h
+++ b/alib2algo/src/automaton/simplify/SingleInitialState.h
@@ -31,7 +31,7 @@ public:
 
 	static automaton::DFA<> convert(const automaton::DFA<>& automaton);
 	static automaton::NFA < > convert(const automaton::NFA < > & automaton);
-	static automaton::EpsilonNFA convert(const automaton::EpsilonNFA& automaton);
+	static automaton::EpsilonNFA < > convert(const automaton::EpsilonNFA < > & automaton);
 	static automaton::ExtendedNFA convert(const automaton::ExtendedNFA& automaton);
 	static automaton::CompactNFA < > convert(const automaton::CompactNFA < > & automaton);
 };
diff --git a/alib2algo/src/automaton/simplify/Trim.cpp b/alib2algo/src/automaton/simplify/Trim.cpp
index d8f28b3181af2b9e7542b68b9e1ed894122723a9..615af0b54b1a028c6c3e52a8328745a92fd24381 100644
--- a/alib2algo/src/automaton/simplify/Trim.cpp
+++ b/alib2algo/src/automaton/simplify/Trim.cpp
@@ -27,7 +27,7 @@ T Trim::trim( const T & fsm ) {
 auto TrimDFA = Trim::RegistratorWrapper<automaton::DFA<>, automaton::DFA<>>(Trim::trim);
 auto TrimNFA = Trim::RegistratorWrapper<automaton::NFA < > , automaton::NFA < > >(Trim::trim);
 auto TrimMultiInitialStateNFA = Trim::RegistratorWrapper<automaton::MultiInitialStateNFA < > , automaton::MultiInitialStateNFA < > >(Trim::trim);
-auto TrimEpsilonNFA = Trim::RegistratorWrapper<automaton::EpsilonNFA, automaton::EpsilonNFA>(Trim::trim);
+auto TrimEpsilonNFA = Trim::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::EpsilonNFA < > >(Trim::trim);
 auto TrimCompactNFA = Trim::RegistratorWrapper<automaton::CompactNFA < >, automaton::CompactNFA < > >(Trim::trim);
 auto TrimExtendedNFA = Trim::RegistratorWrapper<automaton::ExtendedNFA, automaton::ExtendedNFA>(Trim::trim);
 
diff --git a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp
index af3a73e7f376737af6e1a0adb9481edf826f809f..8e55235054e9c2b0c0ee5082740a180626950526 100644
--- a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp
+++ b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp
@@ -47,7 +47,7 @@ T UnreachableStatesRemover::remove( const T & fsm ) {
 	return M;
 }
 
-auto UnreachableStatesRemoverEpsilonNFA = UnreachableStatesRemover::RegistratorWrapper<automaton::EpsilonNFA, automaton::EpsilonNFA>(UnreachableStatesRemover::remove);
+auto UnreachableStatesRemoverEpsilonNFA = UnreachableStatesRemover::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::EpsilonNFA < > >(UnreachableStatesRemover::remove);
 auto UnreachableStatesRemoverNFA = UnreachableStatesRemover::RegistratorWrapper<automaton::NFA < > , automaton::NFA < > >(UnreachableStatesRemover::remove);
 auto UnreachableStatesRemoverCompactNFA = UnreachableStatesRemover::RegistratorWrapper<automaton::CompactNFA < >, automaton::CompactNFA < > >(UnreachableStatesRemover::remove);
 auto UnreachableStatesRemoverExtendedNFA = UnreachableStatesRemover::RegistratorWrapper<automaton::ExtendedNFA, automaton::ExtendedNFA>(UnreachableStatesRemover::remove);
diff --git a/alib2algo/src/automaton/simplify/UselessStatesRemover.cpp b/alib2algo/src/automaton/simplify/UselessStatesRemover.cpp
index 2c46c6057acd3eccb5fc19747c2854c5910f81b4..f3a42af5e26ec04e2115ab50c06270cded6820ef 100644
--- a/alib2algo/src/automaton/simplify/UselessStatesRemover.cpp
+++ b/alib2algo/src/automaton/simplify/UselessStatesRemover.cpp
@@ -48,7 +48,7 @@ T UselessStatesRemover::remove( const T & fsm ) {
 	return M;
 }
 
-auto UselessStatesRemoverEpsilonNFA = UselessStatesRemover::RegistratorWrapper<automaton::EpsilonNFA, automaton::EpsilonNFA>(UselessStatesRemover::remove);
+auto UselessStatesRemoverEpsilonNFA = UselessStatesRemover::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::EpsilonNFA < > >(UselessStatesRemover::remove);
 auto UselessStatesRemoverNFA = UselessStatesRemover::RegistratorWrapper<automaton::NFA < > , automaton::NFA < > >(UselessStatesRemover::remove);
 auto UselessStatesRemoverCompactNFA = UselessStatesRemover::RegistratorWrapper<automaton::CompactNFA < >, automaton::CompactNFA < > >(UselessStatesRemover::remove);
 auto UselessStatesRemoverExtendedNFA = UselessStatesRemover::RegistratorWrapper<automaton::ExtendedNFA, automaton::ExtendedNFA>(UselessStatesRemover::remove);
diff --git a/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.cpp b/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.cpp
index df1e5d47a943054f9c0b39f06600d37cd07e08ad..5d1925587e8180e5164e454df5c4de11b0cf227d 100644
--- a/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.cpp
+++ b/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.cpp
@@ -20,8 +20,8 @@ automaton::Automaton AutomataConcatenationEpsilonTransition::concatenation(const
 	return dispatch(first.getData(), second.getData());
 }
 
-automaton::EpsilonNFA AutomataConcatenationEpsilonTransition::concatenation(const automaton::DFA<>& first, const automaton::DFA<>& second) {
-	automaton::EpsilonNFA res(pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState()));
+automaton::EpsilonNFA < > AutomataConcatenationEpsilonTransition::concatenation(const automaton::DFA<>& first, const automaton::DFA<>& second) {
+	automaton::EpsilonNFA < > res(pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState()));
 
 	for(const auto& symbol : first.getInputAlphabet())
 		res.addInputSymbol(symbol);
@@ -48,10 +48,10 @@ automaton::EpsilonNFA AutomataConcatenationEpsilonTransition::concatenation(cons
 	return res;
 }
 
-auto AutomataConcatenationEpsilonTransitionDFA = AutomataConcatenationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA, automaton::DFA<>>(AutomataConcatenationEpsilonTransition::concatenation);
+auto AutomataConcatenationEpsilonTransitionDFA = AutomataConcatenationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::DFA<>>(AutomataConcatenationEpsilonTransition::concatenation);
 
-automaton::EpsilonNFA AutomataConcatenationEpsilonTransition::concatenation(const automaton::NFA < > & first, const automaton::NFA < > & second) {
-	automaton::EpsilonNFA res(pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState()));
+automaton::EpsilonNFA < > AutomataConcatenationEpsilonTransition::concatenation(const automaton::NFA < > & first, const automaton::NFA < > & second) {
+	automaton::EpsilonNFA < > res(pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState()));
 
 	for(const auto& symbol : first.getInputAlphabet())
 		res.addInputSymbol(symbol);
@@ -80,10 +80,10 @@ automaton::EpsilonNFA AutomataConcatenationEpsilonTransition::concatenation(cons
 	return res;
 }
 
-auto AutomataConcatenationEpsilonTransitionNFA = AutomataConcatenationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA, automaton::NFA < > >(AutomataConcatenationEpsilonTransition::concatenation);
+auto AutomataConcatenationEpsilonTransitionNFA = AutomataConcatenationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::NFA < > >(AutomataConcatenationEpsilonTransition::concatenation);
 
-automaton::EpsilonNFA AutomataConcatenationEpsilonTransition::concatenation(const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) {
-	automaton::EpsilonNFA res(pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState()));
+automaton::EpsilonNFA < > AutomataConcatenationEpsilonTransition::concatenation(const automaton::EpsilonNFA < > & first, const automaton::EpsilonNFA < > & second) {
+	automaton::EpsilonNFA < > res(pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState()));
 
 	for(const auto& symbol : first.getInputAlphabet())
 		res.addInputSymbol(symbol);
@@ -112,7 +112,7 @@ automaton::EpsilonNFA AutomataConcatenationEpsilonTransition::concatenation(cons
 	return res;
 }
 
-auto AutomataConcatenationEpsilonTransitionEpsilonNFA = AutomataConcatenationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA, automaton::EpsilonNFA>(AutomataConcatenationEpsilonTransition::concatenation);
+auto AutomataConcatenationEpsilonTransitionEpsilonNFA = AutomataConcatenationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < > , automaton::EpsilonNFA < > >(AutomataConcatenationEpsilonTransition::concatenation);
 
 } /* namespace transform */
 
diff --git a/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h b/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h
index 64f2bfb8056809134ac0bd1d82cece2fcc79e33b..e661cfea8b44eecf4740ba301abd69da54e6ade1 100644
--- a/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h
+++ b/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h
@@ -24,9 +24,9 @@ class AutomataConcatenationEpsilonTransition : public std::PromotingDoubleDispat
 public:
 	static automaton::Automaton concatenation(const automaton::Automaton& first, const automaton::Automaton& second);
 
-	static automaton::EpsilonNFA concatenation(const automaton::DFA<>& first, const automaton::DFA<>& second);
-	static automaton::EpsilonNFA concatenation(const automaton::NFA < > & first, const automaton::NFA < > & second);
-	static automaton::EpsilonNFA concatenation(const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second);
+	static automaton::EpsilonNFA < > concatenation(const automaton::DFA<>& first, const automaton::DFA<>& second);
+	static automaton::EpsilonNFA < > concatenation(const automaton::NFA < > & first, const automaton::NFA < > & second);
+	static automaton::EpsilonNFA < > concatenation(const automaton::EpsilonNFA < > & first, const automaton::EpsilonNFA < > & second);
 };
 
 } /* namespace transform */
diff --git a/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.cpp b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.cpp
index c19e109b631c4d223d573f78ad93945f9ab9041b..b636b0e4f81a2c3b788ede30f32fd99b3473584f 100644
--- a/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.cpp
+++ b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.cpp
@@ -20,7 +20,7 @@ automaton::Automaton AutomataUnionEpsilonTransition::unification(const automaton
 	return dispatch(first.getData(), second.getData());
 }
 
-automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) {
+automaton::EpsilonNFA < > AutomataUnionEpsilonTransition::unification(const automaton::EpsilonNFA < > & first, const automaton::EpsilonNFA < > & second) {
 	std::set<label::Label> states;
 	for(const auto& q : first.getStates())
 		states.insert(pairLabel(label::labelFrom(AUTOMATON_FIRST), q));
@@ -28,7 +28,7 @@ automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automato
 		states.insert(pairLabel(label::labelFrom(AUTOMATON_SECOND), q));
 
 	label::Label q0 = label::createUniqueLabel(label::InitialStateLabel::INITIAL_STATE_LABEL, states);
-	automaton::EpsilonNFA res(q0);
+	automaton::EpsilonNFA < > res(q0);
 
 	for(const auto& a : first.getInputAlphabet())
 		res.addInputSymbol(a);
@@ -57,9 +57,9 @@ automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automato
 	return res;
 }
 
-auto AutomataUnionEpsilonTransitionEpsilonNFA = AutomataUnionEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA, automaton::EpsilonNFA>(AutomataUnionEpsilonTransition::unification);
+auto AutomataUnionEpsilonTransitionEpsilonNFA = AutomataUnionEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::EpsilonNFA < > >(AutomataUnionEpsilonTransition::unification);
 
-automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automaton::NFA < > & first, const automaton::NFA < > & second) {
+automaton::EpsilonNFA < > AutomataUnionEpsilonTransition::unification(const automaton::NFA < > & first, const automaton::NFA < > & second) {
 	std::set<label::Label> states;
 	for(const auto& q : first.getStates())
 		states.insert(pairLabel(label::labelFrom(AUTOMATON_FIRST), q));
@@ -67,7 +67,7 @@ automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automato
 		states.insert(pairLabel(label::labelFrom(AUTOMATON_SECOND), q));
 
 	label::Label q0 = label::createUniqueLabel(label::InitialStateLabel::INITIAL_STATE_LABEL, states);
-	automaton::EpsilonNFA res(q0);
+	automaton::EpsilonNFA < > res(q0);
 
 	for(const auto& a : first.getInputAlphabet())
 		res.addInputSymbol(a);
@@ -96,9 +96,9 @@ automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automato
 	return res;
 }
 
-auto AutomataUnionEpsilonTransitionNFA = AutomataUnionEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA, automaton::NFA < > >(AutomataUnionEpsilonTransition::unification);
+auto AutomataUnionEpsilonTransitionNFA = AutomataUnionEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::NFA < > >(AutomataUnionEpsilonTransition::unification);
 
-automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automaton::DFA<>& first, const automaton::DFA<>& second) {
+automaton::EpsilonNFA < > AutomataUnionEpsilonTransition::unification(const automaton::DFA<>& first, const automaton::DFA<>& second) {
 	std::set<label::Label> states;
 	for(const auto& q : first.getStates())
 		states.insert(pairLabel(label::labelFrom(AUTOMATON_FIRST), q));
@@ -106,7 +106,7 @@ automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automato
 		states.insert(pairLabel(label::labelFrom(AUTOMATON_SECOND), q));
 
 	label::Label q0 = label::createUniqueLabel(label::InitialStateLabel::INITIAL_STATE_LABEL, states);
-	automaton::EpsilonNFA res(q0);
+	automaton::EpsilonNFA < > res(q0);
 
 	for(const auto& a : first.getInputAlphabet())
 		res.addInputSymbol(a);
@@ -133,7 +133,7 @@ automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automato
 	return res;
 }
 
-auto AutomataUnionEpsilonTransitionDFA = AutomataUnionEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA, automaton::DFA<>>(AutomataUnionEpsilonTransition::unification);
+auto AutomataUnionEpsilonTransitionDFA = AutomataUnionEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::DFA<>>(AutomataUnionEpsilonTransition::unification);
 
 } /* namespace transform */
 
diff --git a/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h
index 87a60f1eee3c934f2374fb56afb88f1f5c22ac00..50650b5a77af1a5fbcbb2d38c3326fdea0e7e02c 100644
--- a/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h
+++ b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h
@@ -24,9 +24,9 @@ class AutomataUnionEpsilonTransition : public std::PromotingDoubleDispatch<Autom
 public:
 	static automaton::Automaton unification(const automaton::Automaton& first, const automaton::Automaton& second);
 
-	static automaton::EpsilonNFA unification(const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second);
-	static automaton::EpsilonNFA unification(const automaton::NFA < > & first, const automaton::NFA < > & second);
-	static automaton::EpsilonNFA unification(const automaton::DFA<>& first, const automaton::DFA<>& second);
+	static automaton::EpsilonNFA < > unification(const automaton::EpsilonNFA < > & first, const automaton::EpsilonNFA < > & second);
+	static automaton::EpsilonNFA < > unification(const automaton::NFA < > & first, const automaton::NFA < > & second);
+	static automaton::EpsilonNFA < > unification(const automaton::DFA<>& first, const automaton::DFA<>& second);
 
 };
 
diff --git a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
index 54707362b0fc2d7c3f52b82c3dba8ced8cbd7883..d222a412626bc462501a7d220ec14383bd07e8e5 100644
--- a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
+++ b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
@@ -16,8 +16,8 @@ automaton::Automaton AutomatonIterationEpsilonTransition::iteration(const automa
 }
 
 template<class T>
-automaton::EpsilonNFA AutomatonIterationEpsilonTransition::iteration(const T& automaton) {
-	automaton::EpsilonNFA res(automaton);
+automaton::EpsilonNFA < > AutomatonIterationEpsilonTransition::iteration(const T& automaton) {
+	automaton::EpsilonNFA < > res(automaton);
 
 	for(const auto&q : automaton.getFinalStates())
 		res.addTransition(q, automaton.getInitialState());
@@ -26,9 +26,9 @@ automaton::EpsilonNFA AutomatonIterationEpsilonTransition::iteration(const T& au
 	return res;
 }
 
-auto AutomatonIterationEpsilonTransitionDFA = AutomatonIterationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA, automaton::DFA<>>(AutomatonIterationEpsilonTransition::iteration);
-auto AutomatonIterationEpsilonTransitionNFA = AutomatonIterationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA, automaton::NFA < > >(AutomatonIterationEpsilonTransition::iteration);
-auto AutomatonIterationEpsilonTransitionEpsilonNFA = AutomatonIterationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA, automaton::EpsilonNFA>(AutomatonIterationEpsilonTransition::iteration);
+auto AutomatonIterationEpsilonTransitionDFA = AutomatonIterationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::DFA<>>(AutomatonIterationEpsilonTransition::iteration);
+auto AutomatonIterationEpsilonTransitionNFA = AutomatonIterationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::NFA < > >(AutomatonIterationEpsilonTransition::iteration);
+auto AutomatonIterationEpsilonTransitionEpsilonNFA = AutomatonIterationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::EpsilonNFA < > >(AutomatonIterationEpsilonTransition::iteration);
 
 } /* namespace transform */
 
diff --git a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h
index 17d3b5c53ee662f958ac679e8b12a2b42169f81f..f85041584e9ace22cdc2fafc8fb77d3cd35e7d43 100644
--- a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h
+++ b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h
@@ -25,7 +25,7 @@ public:
 	static automaton::Automaton iteration(const automaton::Automaton& automaton);
 
 	template<class T>
-	static automaton::EpsilonNFA iteration(const T& automaton);
+	static automaton::EpsilonNFA < > iteration(const T& automaton);
 };
 
 } /* namespace transform */
diff --git a/alib2algo/src/regexp/convert/ToAutomatonThompson.cpp b/alib2algo/src/regexp/convert/ToAutomatonThompson.cpp
index 333bc6c089e828753da0b6a1c29c515f50734713..3ecbd3e115d31c9fd9e8cadca459c166467fadc1 100644
--- a/alib2algo/src/regexp/convert/ToAutomatonThompson.cpp
+++ b/alib2algo/src/regexp/convert/ToAutomatonThompson.cpp
@@ -13,16 +13,16 @@ namespace regexp {
 
 namespace convert {
 
-automaton::EpsilonNFA ToAutomatonThompson::convert(const regexp::RegExp& regexp) {
+automaton::EpsilonNFA < > ToAutomatonThompson::convert(const regexp::RegExp& regexp) {
 	return dispatch(regexp.getData());
 }
 
 template<class T>
-automaton::EpsilonNFA ToAutomatonThompson::convert(const T& regexp) {
+automaton::EpsilonNFA < > ToAutomatonThompson::convert(const T& regexp) {
 	//FIXME use actual algorithms that implement product alternation and iteration of re over automata and remove terrible TERRIBLE hack with dummy initial state
-	std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*> out(automaton::EpsilonNFA(label::labelFrom(0)), 1, nullptr, nullptr);
+	std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*> out(automaton::EpsilonNFA < >(label::labelFrom(0)), 1, nullptr, nullptr);
 
-	automaton::EpsilonNFA& automaton = std::get<0>(out);
+	automaton::EpsilonNFA < >& automaton = std::get<0>(out);
 	automaton.setInputAlphabet(regexp.getAlphabet());
 
 	regexp.getRegExp().Accept((void*) &out, ToAutomatonThompson::TO_AUTOMATON_THOMPSON);
@@ -35,15 +35,15 @@ automaton::EpsilonNFA ToAutomatonThompson::convert(const T& regexp) {
 	return automaton;
 }
 
-auto ToAutomatonThompsonFormalRegExp = ToAutomatonThompson::RegistratorWrapper<automaton::EpsilonNFA, regexp::FormalRegExp>(ToAutomatonThompson::convert);
-auto ToAutomatonThompsonUnboundedRegExp = ToAutomatonThompson::RegistratorWrapper<automaton::EpsilonNFA, regexp::UnboundedRegExp>(ToAutomatonThompson::convert);
+auto ToAutomatonThompsonFormalRegExp = ToAutomatonThompson::RegistratorWrapper<automaton::EpsilonNFA < >, regexp::FormalRegExp>(ToAutomatonThompson::convert);
+auto ToAutomatonThompsonUnboundedRegExp = ToAutomatonThompson::RegistratorWrapper<automaton::EpsilonNFA < >, regexp::UnboundedRegExp>(ToAutomatonThompson::convert);
 
 // ----------------------------------------------------------------------------
 
 void ToAutomatonThompson::Visit(void* userData, const regexp::FormalRegExpAlternation& alternation) const
 {
-	std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*>*) userData;
-	automaton::EpsilonNFA& automaton = std::get<0>(out);
+	std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*>*) userData;
+	automaton::EpsilonNFA < >& automaton = std::get<0>(out);
 
 	label::Label head = label::labelFrom(std::get<1>(out)++);
 	label::Label tail = label::labelFrom(std::get<1>(out)++);
@@ -64,9 +64,9 @@ void ToAutomatonThompson::Visit(void* userData, const regexp::FormalRegExpAltern
 
 void ToAutomatonThompson::Visit(void* userData, const regexp::FormalRegExpConcatenation& concatenation) const
 {
-	std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*>*) userData;
+	std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*>*) userData;
 
-	automaton::EpsilonNFA& automaton = std::get<0>(out);
+	automaton::EpsilonNFA < >& automaton = std::get<0>(out);
 
 	static_cast<const regexp::FormalRegExpElement&>(concatenation.getLeftElement()).Accept(userData, *this);
 	const label::Label* leftHead = std::get<2>(out);
@@ -81,9 +81,9 @@ void ToAutomatonThompson::Visit(void* userData, const regexp::FormalRegExpConcat
 
 void ToAutomatonThompson::Visit(void* userData, const regexp::FormalRegExpIteration& iteration) const
 {
-	std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*>*) userData;
+	std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*>*) userData;
 
-	automaton::EpsilonNFA& automaton = std::get<0>(out);
+	automaton::EpsilonNFA < >& automaton = std::get<0>(out);
 
 	label::Label head = label::labelFrom(std::get<1>(out)++);
 	label::Label tail = label::labelFrom(std::get<1>(out)++);
@@ -102,9 +102,9 @@ void ToAutomatonThompson::Visit(void* userData, const regexp::FormalRegExpIterat
 
 void ToAutomatonThompson::Visit(void* userData, const regexp::FormalRegExpSymbol& symbol) const
 {
-	std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*>*) userData;
+	std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*>*) userData;
 
-	automaton::EpsilonNFA& automaton = std::get<0>(out);
+	automaton::EpsilonNFA < >& automaton = std::get<0>(out);
 
 	label::Label head = label::labelFrom(std::get<1>(out)++);
 	label::Label tail = label::labelFrom(std::get<1>(out)++);
@@ -118,9 +118,9 @@ void ToAutomatonThompson::Visit(void* userData, const regexp::FormalRegExpSymbol
 
 void ToAutomatonThompson::Visit(void* userData, const regexp::FormalRegExpEpsilon&) const
 {
-	std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*>*) userData;
+	std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*>*) userData;
 
-	automaton::EpsilonNFA& automaton = std::get<0>(out);
+	automaton::EpsilonNFA < >& automaton = std::get<0>(out);
 
 	label::Label head = label::labelFrom(std::get<1>(out)++);
 	label::Label tail = label::labelFrom(std::get<1>(out)++);
@@ -134,9 +134,9 @@ void ToAutomatonThompson::Visit(void* userData, const regexp::FormalRegExpEpsilo
 
 void ToAutomatonThompson::Visit(void* userData, const regexp::FormalRegExpEmpty&) const
 {
-	std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*>*) userData;
+	std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*>*) userData;
 
-	automaton::EpsilonNFA& automaton = std::get<0>(out);
+	automaton::EpsilonNFA < >& automaton = std::get<0>(out);
 
 	label::Label head = label::labelFrom(std::get<1>(out)++);
 	label::Label tail = label::labelFrom(std::get<1>(out)++);
@@ -151,8 +151,8 @@ void ToAutomatonThompson::Visit(void* userData, const regexp::FormalRegExpEmpty&
 
 void ToAutomatonThompson::Visit(void* userData, const regexp::UnboundedRegExpAlternation& alternation) const
 {
-	std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*>*) userData;
-	automaton::EpsilonNFA& automaton = std::get<0>(out);
+	std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*>*) userData;
+	automaton::EpsilonNFA < >& automaton = std::get<0>(out);
 
 	label::Label head = label::labelFrom(std::get<1>(out)++);
 	label::Label tail = label::labelFrom(std::get<1>(out)++);
@@ -172,8 +172,8 @@ void ToAutomatonThompson::Visit(void* userData, const regexp::UnboundedRegExpAlt
 
 void ToAutomatonThompson::Visit(void* userData, const regexp::UnboundedRegExpConcatenation& concatenation) const
 {
-	std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*>*) userData;
-	automaton::EpsilonNFA& automaton = std::get<0>(out);
+	std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*>*) userData;
+	automaton::EpsilonNFA < >& automaton = std::get<0>(out);
 
 	std::vector<std::pair<const label::Label*, const label::Label*>> tails;
 	for(const auto& element : concatenation.getElements())
@@ -191,8 +191,8 @@ void ToAutomatonThompson::Visit(void* userData, const regexp::UnboundedRegExpCon
 
 void ToAutomatonThompson::Visit(void* userData, const regexp::UnboundedRegExpIteration& iteration) const
 {
-	std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*>*) userData;
-	automaton::EpsilonNFA& automaton = std::get<0>(out);
+	std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*>*) userData;
+	automaton::EpsilonNFA < >& automaton = std::get<0>(out);
 
 	label::Label head = label::labelFrom(std::get<1>(out)++);
 	label::Label tail = label::labelFrom(std::get<1>(out)++);
@@ -211,8 +211,8 @@ void ToAutomatonThompson::Visit(void* userData, const regexp::UnboundedRegExpIte
 
 void ToAutomatonThompson::Visit(void* userData, const regexp::UnboundedRegExpSymbol& symbol) const
 {
-	std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*>*) userData;
-	automaton::EpsilonNFA& automaton = std::get<0>(out);
+	std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*>*) userData;
+	automaton::EpsilonNFA < >& automaton = std::get<0>(out);
 
 	label::Label head = label::labelFrom(std::get<1>(out)++);
 	label::Label tail = label::labelFrom(std::get<1>(out)++);
@@ -226,8 +226,8 @@ void ToAutomatonThompson::Visit(void* userData, const regexp::UnboundedRegExpSym
 
 void ToAutomatonThompson::Visit(void* userData, const regexp::UnboundedRegExpEpsilon&) const
 {
-	std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*>*) userData;
-	automaton::EpsilonNFA& automaton = std::get<0>(out);
+	std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*>*) userData;
+	automaton::EpsilonNFA < >& automaton = std::get<0>(out);
 
 	label::Label head = label::labelFrom(std::get<1>(out)++);
 	label::Label tail = label::labelFrom(std::get<1>(out)++);
@@ -241,8 +241,8 @@ void ToAutomatonThompson::Visit(void* userData, const regexp::UnboundedRegExpEps
 
 void ToAutomatonThompson::Visit(void* userData, const regexp::UnboundedRegExpEmpty&) const
 {
-	std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA, int, const label::Label*, const label::Label*>*) userData;
-	automaton::EpsilonNFA& automaton = std::get<0>(out);
+	std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*> &out = *(std::tuple<automaton::EpsilonNFA < >, int, const label::Label*, const label::Label*>*) userData;
+	automaton::EpsilonNFA < >& automaton = std::get<0>(out);
 
 	label::Label head = label::labelFrom(std::get<1>(out)++);
 	label::Label tail = label::labelFrom(std::get<1>(out)++);
diff --git a/alib2algo/src/regexp/convert/ToAutomatonThompson.h b/alib2algo/src/regexp/convert/ToAutomatonThompson.h
index 5d639411c63f9e51789f32c5f3339c9f32892a61..155be95ec73408c8bb5b1c5b8f15472f23eb0998 100644
--- a/alib2algo/src/regexp/convert/ToAutomatonThompson.h
+++ b/alib2algo/src/regexp/convert/ToAutomatonThompson.h
@@ -29,7 +29,7 @@ namespace convert {
  *  http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.21.7450&rep=rep1&type=ps
  *  Melichar 2.112
  */
-class ToAutomatonThompson : public std::SingleDispatch<ToAutomatonThompson, automaton::EpsilonNFA, regexp::RegExpBase>, regexp::FormalRegExpElementVisitor, regexp::UnboundedRegExpElementVisitor {
+class ToAutomatonThompson : public std::SingleDispatch<ToAutomatonThompson, automaton::EpsilonNFA < >, regexp::RegExpBase>, regexp::FormalRegExpElementVisitor, regexp::UnboundedRegExpElementVisitor {
 public:
 	ToAutomatonThompson() {}
 
@@ -38,10 +38,10 @@ public:
 	 * @param regexp regexp to convert
 	 * @return nondeterministic finite automaton with epsilon transitions accepting language described by the regexp
 	 */
-	static automaton::EpsilonNFA convert(const regexp::RegExp& regexp);
+	static automaton::EpsilonNFA < > convert(const regexp::RegExp& regexp);
 
 	template<class T>
-	static automaton::EpsilonNFA convert(const T& regexp);
+	static automaton::EpsilonNFA < > convert(const T& regexp);
 
 private:
 	 void Visit(void*, const regexp::UnboundedRegExpAlternation& alternation) const;
diff --git a/alib2algo/src/stringology/exact/ExactFactorAutomaton.cpp b/alib2algo/src/stringology/exact/ExactFactorAutomaton.cpp
index 4536dbaeac5ff9fbecfe6d6a5fe8aa6e73abc883..5a679c98890f2350869b333f8f62c39be5eafc2f 100644
--- a/alib2algo/src/stringology/exact/ExactFactorAutomaton.cpp
+++ b/alib2algo/src/stringology/exact/ExactFactorAutomaton.cpp
@@ -19,8 +19,8 @@ automaton::Automaton ExactFactorAutomaton::construct(const string::String& text)
 	return dispatch(text.getData());
 }
 
-automaton::EpsilonNFA ExactFactorAutomaton::construct(const string::LinearString& text) {
-	automaton::EpsilonNFA res(label::labelFrom(0));
+automaton::EpsilonNFA < > ExactFactorAutomaton::construct(const string::LinearString& text) {
+	automaton::EpsilonNFA < > res(label::labelFrom(0));
 	res.addFinalState(label::labelFrom(0));
 	res.setInputAlphabet(text.getAlphabet());
 	int i = 1;
@@ -34,7 +34,7 @@ automaton::EpsilonNFA ExactFactorAutomaton::construct(const string::LinearString
 	return res;
 }
 
-auto ExactFactorAutomatonLinearString = ExactFactorAutomaton::RegistratorWrapper<automaton::EpsilonNFA, string::LinearString>(ExactFactorAutomaton::construct);
+auto ExactFactorAutomatonLinearString = ExactFactorAutomaton::RegistratorWrapper<automaton::EpsilonNFA < >, string::LinearString>(ExactFactorAutomaton::construct);
 
 } /* namespace exact */
 
diff --git a/alib2algo/src/stringology/exact/ExactFactorAutomaton.h b/alib2algo/src/stringology/exact/ExactFactorAutomaton.h
index 1b2ec32e409c1b4f129f874ceac6057121ed70c9..ba7d395db42342f4b69804e22afce5c6be030030 100644
--- a/alib2algo/src/stringology/exact/ExactFactorAutomaton.h
+++ b/alib2algo/src/stringology/exact/ExactFactorAutomaton.h
@@ -26,7 +26,7 @@ public:
 	 */
 	static automaton::Automaton construct(const string::String& text);
 
-	static automaton::EpsilonNFA construct(const string::LinearString& text);
+	static automaton::EpsilonNFA < > construct(const string::LinearString& text);
 };
 
 } /* namespace exact */
diff --git a/alib2algo/src/stringology/exact/ExactMultiNondeterministicSubsequenceAutomaton.cpp b/alib2algo/src/stringology/exact/ExactMultiNondeterministicSubsequenceAutomaton.cpp
index 4fff8abbd31c8efaab1129bcb592c091746ed5ea..7449a5b0ee61083ab3d9ef21601cebd463935fd2 100644
--- a/alib2algo/src/stringology/exact/ExactMultiNondeterministicSubsequenceAutomaton.cpp
+++ b/alib2algo/src/stringology/exact/ExactMultiNondeterministicSubsequenceAutomaton.cpp
@@ -18,8 +18,8 @@ automaton::Automaton ExactMultiNondeterministicSubsequenceAutomaton::construct(c
 	return automaton::Automaton(ExactMultiNondeterministicSubsequenceAutomaton::construct(common::ContainerConverter<std::set<string::LinearString>, std::set<string::String>, string::LinearString>::convert(texts)));
 }
 
-automaton::EpsilonNFA ExactMultiNondeterministicSubsequenceAutomaton::construct(const std::set<string::LinearString>& texts) {
-	automaton::EpsilonNFA res(label::labelFrom(0));
+automaton::EpsilonNFA < > ExactMultiNondeterministicSubsequenceAutomaton::construct(const std::set<string::LinearString>& texts) {
+	automaton::EpsilonNFA < > res(label::labelFrom(0));
 	res.addFinalState(label::labelFrom(0));
 
 	int j = 0;
diff --git a/alib2algo/src/stringology/exact/ExactMultiNondeterministicSubsequenceAutomaton.h b/alib2algo/src/stringology/exact/ExactMultiNondeterministicSubsequenceAutomaton.h
index eec9e5c0d47edfe22ec4ffd35ad1655b02b958b6..746e0f2cb9093b512bddde1823895d3d4fbb2cb3 100644
--- a/alib2algo/src/stringology/exact/ExactMultiNondeterministicSubsequenceAutomaton.h
+++ b/alib2algo/src/stringology/exact/ExactMultiNondeterministicSubsequenceAutomaton.h
@@ -25,7 +25,7 @@ public:
 	 */
 	static automaton::Automaton construct(const std::set<string::String>& text);
 
-	static automaton::EpsilonNFA construct(const std::set<string::LinearString>& text);
+	static automaton::EpsilonNFA < > construct(const std::set<string::LinearString>& text);
 };
 
 } /* namespace exact */
diff --git a/alib2algo/src/stringology/exact/ExactNondeterministicSubsequenceAutomaton.cpp b/alib2algo/src/stringology/exact/ExactNondeterministicSubsequenceAutomaton.cpp
index f9b1a5b5f05d164010c2a668aaef776ed3066981..48bbd2e973d5de5802a437c2e10a7636b5b5036f 100644
--- a/alib2algo/src/stringology/exact/ExactNondeterministicSubsequenceAutomaton.cpp
+++ b/alib2algo/src/stringology/exact/ExactNondeterministicSubsequenceAutomaton.cpp
@@ -19,8 +19,8 @@ automaton::Automaton ExactNondeterministicSubsequenceAutomaton::construct(const
 	return dispatch(text.getData());
 }
 
-automaton::EpsilonNFA ExactNondeterministicSubsequenceAutomaton::construct(const string::LinearString& text) {
-	automaton::EpsilonNFA res(label::labelFrom(0));
+automaton::EpsilonNFA < > ExactNondeterministicSubsequenceAutomaton::construct(const string::LinearString& text) {
+	automaton::EpsilonNFA < > res(label::labelFrom(0));
 	res.addFinalState(label::labelFrom(0));
 	res.setInputAlphabet(text.getAlphabet());
 
@@ -36,7 +36,7 @@ automaton::EpsilonNFA ExactNondeterministicSubsequenceAutomaton::construct(const
 	return res;
 }
 
-auto ExactNondeterministicSubsequenceAutomatonLinearString = ExactNondeterministicSubsequenceAutomaton::RegistratorWrapper<automaton::EpsilonNFA, string::LinearString>( ExactNondeterministicSubsequenceAutomaton::construct );
+auto ExactNondeterministicSubsequenceAutomatonLinearString = ExactNondeterministicSubsequenceAutomaton::RegistratorWrapper<automaton::EpsilonNFA < >, string::LinearString>( ExactNondeterministicSubsequenceAutomaton::construct );
 
 } /* namespace exact */
 
diff --git a/alib2algo/src/stringology/exact/ExactNondeterministicSubsequenceAutomaton.h b/alib2algo/src/stringology/exact/ExactNondeterministicSubsequenceAutomaton.h
index 13f3b810c90bd41f12b70e51dd32c74e2bfa13be..77846c7d386b4a7f2372d57a5177b1e749fb0250 100644
--- a/alib2algo/src/stringology/exact/ExactNondeterministicSubsequenceAutomaton.h
+++ b/alib2algo/src/stringology/exact/ExactNondeterministicSubsequenceAutomaton.h
@@ -26,7 +26,7 @@ public:
 	 */
 	static automaton::Automaton construct(const string::String& text);
 
-	static automaton::EpsilonNFA construct(const string::LinearString& text);
+	static automaton::EpsilonNFA < > construct(const string::LinearString& text);
 };
 
 } /* namespace exact */
diff --git a/alib2algo/src/stringology/exact/SuffixAutomaton.cpp b/alib2algo/src/stringology/exact/SuffixAutomaton.cpp
index e9a8d11fd097a3072e4a1c3c923e6b523ce0fc62..2b621264538cebf6fa5399de55e063f3b758d1e5 100644
--- a/alib2algo/src/stringology/exact/SuffixAutomaton.cpp
+++ b/alib2algo/src/stringology/exact/SuffixAutomaton.cpp
@@ -18,7 +18,7 @@ automaton::Automaton SuffixAutomaton::naiveConstruct ( const string::String & pa
 }
 
 automaton::DFA<> SuffixAutomaton::naiveConstruct ( const string::LinearString & pattern ) {
-    automaton::EpsilonNFA nfaSuffixAutomaton ( label::labelFrom ( 0 ) );
+    automaton::EpsilonNFA < > nfaSuffixAutomaton ( label::labelFrom ( 0 ) );
 
     nfaSuffixAutomaton.setInputAlphabet ( pattern.getAlphabet ( ) );
 
@@ -35,6 +35,7 @@ automaton::DFA<> SuffixAutomaton::naiveConstruct ( const string::LinearString &
 
     automaton::DFA<> minimalSuffixAutomaton = automaton::simplify::Minimize::minimize ( automaton::determinize::Determinize::determinize ( automaton::simplify::EpsilonRemoverIncoming::remove ( nfaSuffixAutomaton ) ) );
 
+    // FIXME Trim? and is this even supposed to be here?
     label::Label failState = label::Label ( label::LabelSetLabel ( { } ) );
 
     auto transitionsToFailState = minimalSuffixAutomaton.getTransitionsToState ( failState );
diff --git a/alib2algo/test-src/automaton/properties/EpsilonClosureTest.cpp b/alib2algo/test-src/automaton/properties/EpsilonClosureTest.cpp
index 401cff70e0c872445e33403c3641e08557f38e1f..cae442c1c1a4a2f2a47352b4d061cf9b31b17af4 100644
--- a/alib2algo/test-src/automaton/properties/EpsilonClosureTest.cpp
+++ b/alib2algo/test-src/automaton/properties/EpsilonClosureTest.cpp
@@ -26,7 +26,7 @@ void EpsilonClosureTest::testEpsilonClosure() {
 	label::Label q8 = label::labelFrom ("q8");
 	label::Label q9 = label::labelFrom ("q9");
 
-	automaton::EpsilonNFA automaton(q0);
+	automaton::EpsilonNFA < > automaton(q0);
 	automaton.setStates({q0, q1, q2, q3, q4, q5, q6, q7, q8, q9});
 
 	automaton.addTransition(q0, q1);
diff --git a/alib2algo/test-src/regexp/toAutomaton/re2faTest.cpp b/alib2algo/test-src/regexp/toAutomaton/re2faTest.cpp
index 47ba5958726f778eefc61076373f5dff6d107fa2..4e78dcd2dbbb0d24ccce89f118188c29b32e35be 100644
--- a/alib2algo/test-src/regexp/toAutomaton/re2faTest.cpp
+++ b/alib2algo/test-src/regexp/toAutomaton/re2faTest.cpp
@@ -28,11 +28,11 @@ void re2faTest::testThompson() {
 	std::string input = "a+a* b*";
 	regexp::RegExp regexp1 = alib::StringDataFactory::fromString<regexp::RegExp>(input);
 
-	automaton::EpsilonNFA enfa1 = regexp::convert::ToAutomatonThompson::convert(regexp1);
+	automaton::EpsilonNFA < > enfa1 = regexp::convert::ToAutomatonThompson::convert(regexp1);
 
 	regexp::RegExp regexp2( automaton::convert::ToRegExpAlgebraic::convert( enfa1) );
 
-	automaton::EpsilonNFA enfa2 = regexp::convert::ToAutomatonThompson::convert(regexp2);
+	automaton::EpsilonNFA < > enfa2 = regexp::convert::ToAutomatonThompson::convert(regexp2);
 
 	automaton::Automaton nfa1 = automaton::simplify::EpsilonRemoverOutgoing::remove(automaton::Automaton(enfa1));
 	automaton::Automaton nfa2 = automaton::simplify::EpsilonRemoverOutgoing::remove(automaton::Automaton(enfa2));
diff --git a/alib2data/src/automaton/AutomatonFeatures.h b/alib2data/src/automaton/AutomatonFeatures.h
index c268aa8c2335caf67c487adcf1ba37f4df99518d..0bf3c5a926e3df65bd7e73bab0315e8dc7fcfaae 100644
--- a/alib2data/src/automaton/AutomatonFeatures.h
+++ b/alib2data/src/automaton/AutomatonFeatures.h
@@ -10,6 +10,7 @@
 
 #include <alphabet/Symbol.h>
 #include <label/Label.h>
+#include <string/Epsilon.h>
 
 namespace automaton {
 
@@ -39,6 +40,7 @@ class Automaton;
 class AutomatonBase;
 enum class Shift;
 
+template<class SymbolType = typename alphabet::Symbol, class EpsilonType = typename string::Epsilon, class StateType = typename label::Label >
 class EpsilonNFA;
 template<class SymbolType = typename alphabet::Symbol, class StateType = typename label::Label >
 class NFA;
diff --git a/alib2data/src/automaton/FSM/CompactNFA.cpp b/alib2data/src/automaton/FSM/CompactNFA.cpp
index 326a07bc7287a978767cb95274b3ae44b6cbc2b7..94a9938c26202104670c43968ffd3c11a01cb505 100644
--- a/alib2data/src/automaton/FSM/CompactNFA.cpp
+++ b/alib2data/src/automaton/FSM/CompactNFA.cpp
@@ -24,7 +24,7 @@ auto compactNFAParserRegister2 = xmlApi < alib::Object >::ParserRegister < autom
 auto CompactNFAFromDFA = castApi::CastRegister < automaton::CompactNFA < >, automaton::DFA < > > ( );
 auto CompactNFAFromNFA = castApi::CastRegister < automaton::CompactNFA < >, automaton::NFA < > > ( );
 auto CompactNFAFromMultiInitialStateNFA = castApi::CastRegister < automaton::CompactNFA < >, automaton::MultiInitialStateNFA < > > ( );
-auto CompactNFAEpsilonNFA = castApi::CastRegister < automaton::CompactNFA < >, automaton::EpsilonNFA > ( );
+auto CompactNFAEpsilonNFA = castApi::CastRegister < automaton::CompactNFA < >, automaton::EpsilonNFA < > > ( );
 auto CompactNFACastBinder = castApi::CastPoolStringBinder < automaton::CompactNFA < > > ( automaton::CompactNFA < >::getXmlTagName() );
 
 } /* namespace alib */
diff --git a/alib2data/src/automaton/FSM/CompactNFA.h b/alib2data/src/automaton/FSM/CompactNFA.h
index 49e9f362268568ad4f58ba908c1542d2a1b9232c..1756b87585da783a712b48015e2341485180ea9d 100644
--- a/alib2data/src/automaton/FSM/CompactNFA.h
+++ b/alib2data/src/automaton/FSM/CompactNFA.h
@@ -49,7 +49,7 @@ protected:
 public:
 	explicit CompactNFA ( StateType initialState );
 	explicit CompactNFA ( std::set < StateType > states, std::set < SymbolType > inputAlphabet, StateType initialState, std::set < StateType > finalStates );
-	explicit CompactNFA ( const EpsilonNFA & other );
+	explicit CompactNFA ( const EpsilonNFA < > & other );
 	explicit CompactNFA ( const MultiInitialStateNFA < > & other );
 	explicit CompactNFA ( const NFA<> & other );
 	explicit CompactNFA ( const DFA<> & other );
@@ -183,7 +183,7 @@ CompactNFA < SymbolType, StateType >::CompactNFA ( StateType initialState ) : Co
 }
 
 template < class SymbolType, class StateType >
-CompactNFA < SymbolType, StateType >::CompactNFA ( const EpsilonNFA & other ) : CompactNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
+CompactNFA < SymbolType, StateType >::CompactNFA ( const EpsilonNFA < > & other ) : CompactNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
 	for ( const auto & transition : other.getTransitions ( ) ) {
 		if ( transition.first.second.is < string::Epsilon > ( ) ) {
 			std::pair < StateType, std::vector < SymbolType > > key = std::make_pair ( transition.first.first, std::vector < SymbolType > { } );
diff --git a/alib2data/src/automaton/FSM/EpsilonNFA.cpp b/alib2data/src/automaton/FSM/EpsilonNFA.cpp
index 19ee490a450e6bbed0067369b7a573e5ae44f4ad..c5b4c3ec966ac7606fd9f63cc7fd3a9d3cdcc410 100644
--- a/alib2data/src/automaton/FSM/EpsilonNFA.cpp
+++ b/alib2data/src/automaton/FSM/EpsilonNFA.cpp
@@ -6,319 +6,20 @@
  */
 
 #include "EpsilonNFA.h"
-#include "MultiInitialStateNFA.h"
-#include "NFA.h"
-#include "DFA.h"
-#include <ostream>
-#include <sstream>
-
-#include <sax/FromXMLParserHelper.h>
-#include "../common/AutomatonFromXMLParser.h"
-#include "../common/AutomatonToXMLComposer.h"
 #include "../Automaton.h"
 #include <object/Object.h>
 #include <XmlApi.hpp>
-#include <cast/CastApi.hpp>
-#include "../../label/InitialStateLabel.h"
-
-namespace automaton {
-
-EpsilonNFA::EpsilonNFA ( std::set < label::Label > states, std::set < alphabet::Symbol > inputAlphabet, label::Label initialState, std::set < label::Label > finalStates ) : std::Components < EpsilonNFA, alphabet::Symbol, std::tuple < InputAlphabet >, std::tuple < >, label::Label, std::tuple < States, FinalStates >, std::tuple < InitialState > > ( std::make_tuple ( std::move ( inputAlphabet ) ), std::tuple < > ( ), std::make_tuple ( std::move ( states ), std::move ( finalStates ) ), std::make_tuple ( std::move ( initialState ) ) ) {
-}
-
-EpsilonNFA::EpsilonNFA ( label::Label initialState ) : EpsilonNFA ( std::set < label::Label > { initialState }, std::set < alphabet::Symbol > { }, initialState, std::set < label::Label > { } ) {
-}
-
-EpsilonNFA::EpsilonNFA ( const MultiInitialStateNFA < > & other ) : EpsilonNFA ( other.getStates ( ) + std::set < label::Label > { label::createUniqueLabel ( label::InitialStateLabel::INITIAL_STATE_LABEL, other.getStates ( ) ) }, other.getInputAlphabet ( ), label::createUniqueLabel ( label::InitialStateLabel::INITIAL_STATE_LABEL, other.getStates ( ) ), other.getFinalStates ( ) ) {
-	for ( const auto & transition : other.getTransitions ( ) ) {
-		std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > > key = std::make_pair ( transition.first.first, std::variant < string::Epsilon, alphabet::Symbol > ( transition.first.second ) );
-		transitions[key] = transition.second;
-	}
-
-	std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > > key = std::make_pair ( this->getInitialState ( ), std::variant < string::Epsilon, alphabet::Symbol > ( string::Epsilon::EPSILON ) );
-	transitions[key] = other.getInitialStates ( );
-}
-
-EpsilonNFA::EpsilonNFA ( const NFA <> & other ) : EpsilonNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
-	for ( const auto & transition : other.getTransitions ( ) ) {
-		std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > > key = std::make_pair ( transition.first.first, std::variant < string::Epsilon, alphabet::Symbol > ( transition.first.second ) );
-		transitions[key] = transition.second;
-	}
-}
-
-EpsilonNFA::EpsilonNFA ( const DFA<> & other ) : EpsilonNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
-	for ( const auto & transition : other.getTransitions ( ) ) {
-		std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > > key = std::make_pair ( transition.first.first, std::variant < string::Epsilon, alphabet::Symbol > ( transition.first.second ) );
-		transitions[key].insert ( transition.second );
-	}
-}
-
-AutomatonBase * EpsilonNFA::clone ( ) const {
-	return new EpsilonNFA ( * this );
-}
-
-AutomatonBase * EpsilonNFA::plunder ( ) && {
-	return new EpsilonNFA ( std::move ( * this ) );
-}
-
-bool EpsilonNFA::addTransition ( label::Label from, std::variant < string::Epsilon, alphabet::Symbol > input, label::Label to ) {
-	if ( !getStates ( ).count ( from ) )
-		throw AutomatonException ( "State \"" + std::to_string ( from ) + "\" doesn't exist." );
-
-	if ( input.is < alphabet::Symbol > ( ) && !getInputAlphabet ( ).count ( input.get < alphabet::Symbol > ( ) ) )
-		throw AutomatonException ( "Input symbol \"" + std::to_string ( input.get < alphabet::Symbol > ( ) ) + "\" doesn't exist." );
-
-	if ( !getStates ( ).count ( to ) )
-		throw AutomatonException ( "State \"" + std::to_string ( to ) + "\" doesn't exist." );
-
-	std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > > key = std::make_pair ( std::move ( from ), std::move ( input ) );
-
-	return transitions[std::move ( key )].insert ( std::move ( to ) ).second;
-}
-
-bool EpsilonNFA::addTransition ( label::Label from, alphabet::Symbol input, label::Label to ) {
-	std::variant < string::Epsilon, alphabet::Symbol > inputVariant ( std::move ( input ) );
-
-	return addTransition ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) );
-}
-
-bool EpsilonNFA::addTransition ( label::Label from, label::Label to ) {
-	std::variant < string::Epsilon, alphabet::Symbol > inputVariant ( string::Epsilon::EPSILON );
-
-	return addTransition ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) );
-}
-
-bool EpsilonNFA::removeTransition ( const label::Label & from, const alphabet::Symbol & input, const label::Label & to ) {
-	std::variant < string::Epsilon, alphabet::Symbol > inputVariant ( input );
-	std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > > key = std::make_pair ( from, inputVariant );
-
-	return transitions[key].erase ( to );
-}
-
-bool EpsilonNFA::removeTransition ( const label::Label & from, const label::Label & to ) {
-	std::variant < string::Epsilon, alphabet::Symbol > inputVariant ( string::Epsilon::EPSILON );
-	std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > > key = std::make_pair ( from, inputVariant );
-
-	return transitions[key].erase ( to );
-}
-
-const std::map < std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > & EpsilonNFA::getTransitions ( ) const {
-	return transitions;
-}
-
-std::map < label::Label, std::set < label::Label > > EpsilonNFA::getEpsilonTransitions ( ) const {
-	std::map < label::Label, std::set < label::Label > > result;
-
-	for ( const std::pair < const std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > & transition : transitions )
-		if ( transition.first.second.is < string::Epsilon > ( ) )
-			result[transition.first.first].insert ( transition.second.begin ( ), transition.second.end ( ) );
-
-	return result;
-}
-
-std::map < std::pair < label::Label, alphabet::Symbol >, std::set < label::Label > > EpsilonNFA::getSymbolTransitions ( ) const {
-	std::map < std::pair < label::Label, alphabet::Symbol >, std::set < label::Label > > result;
-
-	for ( const std::pair < const std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > & transition : transitions )
-		if ( transition.first.second.is < alphabet::Symbol > ( ) )
-			result[std::pair < label::Label, alphabet::Symbol > ( transition.first.first, transition.first.second.get < alphabet::Symbol > ( ) )].insert ( transition.second.begin ( ), transition.second.end ( ) );
-
-	return result;
-}
-
-std::map < std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > EpsilonNFA::getTransitionsFromState ( const label::Label & from ) const {
-	if ( !getStates ( ).count ( from ) )
-		throw AutomatonException ( "State \"" + std::to_string ( from ) + "\" doesn't exist" );
-
-	std::map < std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > transitionsFromState;
-
-	for ( const std::pair < const std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > & transition : transitions )
-		if ( transition.first.first == from )
-			transitionsFromState[transition.first].insert ( transition.second.begin ( ), transition.second.end ( ) );
-
-	return transitionsFromState;
-}
-
-std::map < label::Label, std::set < label::Label > > EpsilonNFA::getEpsilonTransitionsFromState ( const label::Label & from ) const {
-	if ( !getStates ( ).count ( from ) )
-		throw AutomatonException ( "State \"" + std::to_string ( from ) + "\" doesn't exist" );
-
-	std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > > key ( from, std::variant < string::Epsilon, alphabet::Symbol > ( string::Epsilon::EPSILON ) );
-	std::map < label::Label, std::set < label::Label > > res;
-	auto transition = transitions.find ( key );
-
-	if ( transition != transitions.end ( ) )
-		res.insert ( std::make_pair ( from, transition->second ) );
-
-	return res;
-}
-
-std::map < std::pair < label::Label, alphabet::Symbol >, std::set < label::Label > > EpsilonNFA::getSymbolTransitionsFromState ( const label::Label & from ) const {
-	if ( !getStates ( ).count ( from ) )
-		throw AutomatonException ( "State \"" + std::to_string ( from ) + "\" doesn't exist" );
-
-	std::map < std::pair < label::Label, alphabet::Symbol >, std::set < label::Label > > transitionsFromState;
 
-	for ( const std::pair < const std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > & transition : transitions )
-		if ( ( transition.first.first == from ) && transition.first.second.is < alphabet::Symbol > ( ) )
-			transitionsFromState[std::pair < label::Label, alphabet::Symbol > ( transition.first.first, transition.first.second.get < alphabet::Symbol > ( ) )].insert ( transition.second.begin ( ), transition.second.end ( ) );
-
-	return transitionsFromState;
-}
-
-std::map < std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > EpsilonNFA::getTransitionsToState ( const label::Label & to ) const {
-	if ( !getStates ( ).count ( to ) )
-		throw AutomatonException ( "State \"" + std::to_string ( to ) + "\" doesn't exist" );
-
-	std::map < std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > transitionsToState;
-
-	for ( const std::pair < const std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > & transition : transitions )
-		if ( transition.second.find ( to ) != transition.second.end ( ) )
-			transitionsToState[transition.first].insert ( transition.second.begin ( ), transition.second.end ( ) );
-
-	return transitionsToState;
-}
-
-std::map < label::Label, std::set < label::Label > > EpsilonNFA::getEpsilonTransitionsToState ( const label::Label & to ) const {
-	if ( !getStates ( ).count ( to ) )
-		throw AutomatonException ( "State \"" + std::to_string ( to ) + "\" doesn't exist" );
-
-	std::map < label::Label, std::set < label::Label > > transitionsToState;
-
-	for ( const std::pair < const std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > & transition : transitions )
-		if ( ( transition.second.find ( to ) != transition.second.end ( ) ) && transition.first.second.is < string::Epsilon > ( ) )
-			transitionsToState[transition.first.first].insert ( transition.second.begin ( ), transition.second.end ( ) );
-
-	return transitionsToState;
-}
-
-std::map < std::pair < label::Label, alphabet::Symbol >, std::set < label::Label > > EpsilonNFA::getSymbolTransitionsToState ( const label::Label & to ) const {
-	if ( !getStates ( ).count ( to ) )
-		throw AutomatonException ( "State \"" + std::to_string ( to ) + "\" doesn't exist" );
-
-	std::map < std::pair < label::Label, alphabet::Symbol >, std::set < label::Label > > transitionsToState;
-
-	for ( const std::pair < const std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > & transition : transitions )
-		if ( ( transition.second.find ( to ) != transition.second.end ( ) ) && transition.first.second.is < alphabet::Symbol > ( ) )
-			transitionsToState[std::pair < label::Label, alphabet::Symbol > ( transition.first.first, transition.first.second.get < alphabet::Symbol > ( ) )].insert ( transition.second.begin ( ), transition.second.end ( ) );
-
-	return transitionsToState;
-}
-
-bool EpsilonNFA::isEpsilonFree ( ) const {
-	for ( const std::pair < const std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > & transition : transitions )
-		if ( transition.first.second.is < string::Epsilon > ( ) )
-			return false;
-
-	return true;
-}
-
-bool EpsilonNFA::isDeterministic ( ) const {
-	for ( const std::pair < const std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > & transition : transitions )
-		if ( transition.second.size ( ) > 1 )
-			return false;
-
-	return isEpsilonFree ( );
-}
-
-bool EpsilonNFA::isTotal ( ) const {
-	return isDeterministic ( ) && transitions.size ( ) == getInputAlphabet ( ).size ( ) * getStates ( ).size ( );
-}
-
-int EpsilonNFA::compare ( const EpsilonNFA & other ) const {
-	auto first = std::tie ( getStates ( ), getInputAlphabet ( ), getInitialState ( ), getFinalStates ( ), transitions );
-	auto second = std::tie ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ), other.getTransitions ( ) );
-
-	std::compare < decltype ( first ) > comp;
-
-	return comp ( first, second );
-}
-
-void EpsilonNFA::operator >>( std::ostream & out ) const {
-	out << "(EpsilonNFA "
-	    << "states = " << getStates ( )
-	    << "inputAlphabet = " << getInputAlphabet ( )
-	    << "initialState = " << getInitialState ( )
-	    << "finalStates = " << getFinalStates ( )
-	    << "transitions = " << transitions
-	    << ")";
-}
-
-EpsilonNFA::operator std::string ( ) const {
-	std::stringstream ss;
-	ss << * this;
-	return ss.str ( );
-}
-
-EpsilonNFA EpsilonNFA::parse ( std::deque < sax::Token >::iterator & input ) {
-	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, EpsilonNFA::getXmlTagName() );
-
-	std::set < label::Label > states = AutomatonFromXMLParser::parseStates < label::Label > ( input );
-	std::set < alphabet::Symbol > inputSymbols = AutomatonFromXMLParser::parseInputAlphabet < alphabet::Symbol > ( input );
-	label::Label initialState = AutomatonFromXMLParser::parseInitialState < label::Label > ( input );
-	std::set < label::Label > finalStates = AutomatonFromXMLParser::parseFinalStates < label::Label > ( input );
-
-	EpsilonNFA automaton ( std::move ( initialState ) );
-
-	automaton.setStates ( std::move ( states ) );
-	automaton.setInputAlphabet ( std::move ( inputSymbols ) );
-	automaton.setFinalStates ( std::move ( finalStates ) );
-
-	AutomatonFromXMLParser::parseTransitions < EpsilonNFA > ( input, automaton );
-
-	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, EpsilonNFA::getXmlTagName() );
-	return automaton;
-}
-
-void EpsilonNFA::parseTransition ( std::deque < sax::Token >::iterator & input, EpsilonNFA & automaton ) {
-	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "transition" );
-	label::Label from = AutomatonFromXMLParser::parseTransitionFrom < label::Label > ( input );
-	std::variant < string::Epsilon, alphabet::Symbol > inputVariant = AutomatonFromXMLParser::parseTransitionInputEpsilonSymbol < string::Epsilon, alphabet::Symbol > ( input );
-	label::Label to = AutomatonFromXMLParser::parseTransitionTo < label::Label > ( input );
-	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, "transition" );
-
-	automaton.addTransition ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) );
-}
-
-void EpsilonNFA::compose ( std::deque < sax::Token > & out ) const {
-	out.emplace_back ( EpsilonNFA::getXmlTagName(), sax::Token::TokenType::START_ELEMENT );
-
-	AutomatonToXMLComposer::composeStates ( out, this->getStates ( ) );
-	AutomatonToXMLComposer::composeInputAlphabet ( out, this->getInputAlphabet ( ) );
-	AutomatonToXMLComposer::composeInitialState ( out, this->getInitialState ( ) );
-	AutomatonToXMLComposer::composeFinalStates ( out, this->getFinalStates ( ) );
-	composeTransitions ( out );
-
-	out.emplace_back ( EpsilonNFA::getXmlTagName(), sax::Token::TokenType::END_ELEMENT );
-}
-
-void EpsilonNFA::composeTransitions ( std::deque < sax::Token > & out ) const {
-	out.emplace_back ( "transitions", sax::Token::TokenType::START_ELEMENT );
-
-	for ( const auto & transition : this->getTransitions ( ) )
-		for ( const auto & targetState : transition.second ) {
-			out.emplace_back ( "transition", sax::Token::TokenType::START_ELEMENT );
-
-			AutomatonToXMLComposer::composeTransitionFrom ( out, transition.first.first );
-			AutomatonToXMLComposer::composeTransitionInputEpsilonSymbol ( out, transition.first.second );
-			AutomatonToXMLComposer::composeTransitionTo ( out, targetState );
-
-			out.emplace_back ( "transition", sax::Token::TokenType::END_ELEMENT );
-		}
-
-	out.emplace_back ( "transitions", sax::Token::TokenType::END_ELEMENT );
-}
-
-} /* namespace automaton */
+#include <cast/CastApi.hpp>
 
 namespace alib {
 
-auto epsilonNFAParserRegister = xmlApi < automaton::Automaton >::ParserRegister < automaton::EpsilonNFA > ( );
-auto epsilonNFAParserRegister2 = xmlApi < alib::Object >::ParserRegister < automaton::EpsilonNFA > ( );
+auto epsilonNFAParserRegister = xmlApi < automaton::Automaton >::ParserRegister < automaton::EpsilonNFA < > > ( );
+auto epsilonNFAParserRegister2 = xmlApi < alib::Object >::ParserRegister < automaton::EpsilonNFA < > > ( );
 
-auto EpsilonNFAFromDFA = castApi::CastRegister < automaton::EpsilonNFA, automaton::DFA < > > ( );
-auto EpsilonNFAFromNFA = castApi::CastRegister < automaton::EpsilonNFA, automaton::NFA < > > ( );
-auto EpsilonNFAFromMultiInitialStateNFA = castApi::CastRegister < automaton::EpsilonNFA, automaton::MultiInitialStateNFA < > > ( );
-auto EpsilonNFACastBinder = castApi::CastPoolStringBinder < automaton::EpsilonNFA > ( automaton::EpsilonNFA::getXmlTagName() );
+auto EpsilonNFAFromDFA = castApi::CastRegister < automaton::EpsilonNFA < >, automaton::DFA < > > ( );
+auto EpsilonNFAFromNFA = castApi::CastRegister < automaton::EpsilonNFA < >, automaton::NFA < > > ( );
+// auto EpsilonNFAFromMultiInitialStateNFA = castApi::CastRegister < automaton::EpsilonNFA < >, automaton::MultiInitialStateNFA < > > ( ); TODO
+auto EpsilonNFACastBinder = castApi::CastPoolStringBinder < automaton::EpsilonNFA < > > ( automaton::EpsilonNFA < >::getXmlTagName() );
 
 } /* namespace alib */
diff --git a/alib2data/src/automaton/FSM/EpsilonNFA.h b/alib2data/src/automaton/FSM/EpsilonNFA.h
index 5cbe05c2e389e3262e84af305f89006b43006068..cd4b68e3c9f0aba4c24077e93153e49717a83f46 100644
--- a/alib2data/src/automaton/FSM/EpsilonNFA.h
+++ b/alib2data/src/automaton/FSM/EpsilonNFA.h
@@ -8,14 +8,20 @@
 #ifndef EPSILON_NFA_H_
 #define EPSILON_NFA_H_
 
-#include "../AutomatonException.h"
 #include <map>
 #include <variant>
+#include <ostream>
+#include <sstream>
+
+#include <sax/FromXMLParserHelper.h>
 #include <core/components.hpp>
+
+#include "../AutomatonException.h"
 #include "../AutomatonBase.h"
-#include "../../alphabet/Symbol.h"
-#include "../../label/Label.h"
-#include "../../string/Epsilon.h"
+#include "../AutomatonFeatures.h"
+#include "../common/AutomatonFromXMLParser.h"
+#include "../common/AutomatonToXMLComposer.h"
+
 #include "MultiInitialStateNFA.h"
 #include "NFA.h"
 #include "DFA.h"
@@ -31,14 +37,15 @@ class States;
 class FinalStates;
 class InitialState;
 
-class EpsilonNFA : public AutomatonBase, public std::Components < EpsilonNFA, alphabet::Symbol, std::tuple < InputAlphabet >, std::tuple < >, label::Label, std::tuple < States, FinalStates >, std::tuple < InitialState > > {
+template<class SymbolType, class EpsilonType, class StateType >
+class EpsilonNFA : public AutomatonBase, public std::Components < EpsilonNFA < SymbolType, EpsilonType, StateType >, SymbolType, std::tuple < InputAlphabet >, std::tuple < >, StateType, std::tuple < States, FinalStates >, std::tuple < InitialState > > {
 protected:
-	std::map < std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > transitions;
+	std::map < std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > transitions;
 
 public:
-	explicit EpsilonNFA ( label::Label initialState );
-	explicit EpsilonNFA ( std::set < label::Label > states, std::set < alphabet::Symbol > inputAlphabet, label::Label initialState, std::set < label::Label > finalStates );
-	explicit EpsilonNFA ( const MultiInitialStateNFA < > & other );
+	explicit EpsilonNFA ( StateType initialState );
+	explicit EpsilonNFA ( std::set < StateType > states, std::set < SymbolType > inputAlphabet, StateType initialState, std::set < StateType > finalStates );
+//	explicit EpsilonNFA ( const MultiInitialStateNFA < > & other ); TODO
 	explicit EpsilonNFA ( const NFA<> & other );
 	explicit EpsilonNFA ( const DFA<> & other );
 
@@ -46,64 +53,64 @@ public:
 
 	virtual AutomatonBase * plunder ( ) &&;
 
-	const label::Label & getInitialState ( ) const {
-		return accessElement < InitialState > ( ).get ( );
+	const StateType & getInitialState ( ) const {
+		return this->template accessElement < InitialState > ( ).get ( );
 	}
 
-	bool setInitialState ( label::Label state ) {
-		return accessElement < InitialState > ( ).set ( std::move ( state ) );
+	bool setInitialState ( StateType state ) {
+		return this->template accessElement < InitialState > ( ).set ( std::move ( state ) );
 	}
 
-	const std::set < label::Label > & getStates ( ) const {
-		return accessComponent < States > ( ).get ( );
+	const std::set < StateType > & getStates ( ) const {
+		return this->template accessComponent < States > ( ).get ( );
 	}
 
-	bool addState ( label::Label state ) {
-		return accessComponent < States > ( ).add ( std::move ( state ) );
+	bool addState ( StateType state ) {
+		return this->template accessComponent < States > ( ).add ( std::move ( state ) );
 	}
 
-	void setStates ( std::set < label::Label > states ) {
-		accessComponent < States > ( ).set ( std::move ( states ) );
+	void setStates ( std::set < StateType > states ) {
+		this->template accessComponent < States > ( ).set ( std::move ( states ) );
 	}
 
-	void removeState ( const label::Label & state ) {
-		accessComponent < States > ( ).remove ( state );
+	void removeState ( const StateType & state ) {
+		this->template accessComponent < States > ( ).remove ( state );
 	}
 
-	const std::set < label::Label > & getFinalStates ( ) const {
-		return accessComponent < FinalStates > ( ).get ( );
+	const std::set < StateType > & getFinalStates ( ) const {
+		return this->template accessComponent < FinalStates > ( ).get ( );
 	}
 
-	bool addFinalState ( label::Label state ) {
-		return accessComponent < FinalStates > ( ).add ( std::move ( state ) );
+	bool addFinalState ( StateType state ) {
+		return this->template accessComponent < FinalStates > ( ).add ( std::move ( state ) );
 	}
 
-	void setFinalStates ( std::set < label::Label > states ) {
-		accessComponent < FinalStates > ( ).set ( std::move ( states ) );
+	void setFinalStates ( std::set < StateType > states ) {
+		this->template accessComponent < FinalStates > ( ).set ( std::move ( states ) );
 	}
 
-	void removeFinalState ( const label::Label & state ) {
-		accessComponent < FinalStates > ( ).remove ( state );
+	void removeFinalState ( const StateType & state ) {
+		this->template accessComponent < FinalStates > ( ).remove ( state );
 	}
 
-	const std::set < alphabet::Symbol > & getInputAlphabet ( ) const {
-		return accessComponent < InputAlphabet > ( ).get ( );
+	const std::set < SymbolType > & getInputAlphabet ( ) const {
+		return this->template accessComponent < InputAlphabet > ( ).get ( );
 	}
 
-	bool addInputSymbol ( alphabet::Symbol symbol ) {
-		return accessComponent < InputAlphabet > ( ).add ( std::move ( symbol ) );
+	bool addInputSymbol ( SymbolType symbol ) {
+		return this->template accessComponent < InputAlphabet > ( ).add ( std::move ( symbol ) );
 	}
 
-	void addInputSymbols ( std::set < alphabet::Symbol > symbols ) {
-		accessComponent < InputAlphabet > ( ).add ( std::move ( symbols ) );
+	void addInputSymbols ( std::set < SymbolType > symbols ) {
+		this->template accessComponent < InputAlphabet > ( ).add ( std::move ( symbols ) );
 	}
 
-	void setInputAlphabet ( std::set < alphabet::Symbol > symbols ) {
-		accessComponent < InputAlphabet > ( ).set ( std::move ( symbols ) );
+	void setInputAlphabet ( std::set < SymbolType > symbols ) {
+		this->template accessComponent < InputAlphabet > ( ).set ( std::move ( symbols ) );
 	}
 
-	void removeInputSymbol ( const alphabet::Symbol & symbol ) {
-		accessComponent < InputAlphabet > ( ).remove ( symbol );
+	void removeInputSymbol ( const SymbolType & symbol ) {
+		this->template accessComponent < InputAlphabet > ( ).remove ( symbol );
 	}
 
 	/**
@@ -113,7 +120,7 @@ public:
 	 * @param next next state
 	 * @throws AutomatonException when transition already exists or when transition contains state or symbol not present in the automaton
 	 */
-	bool addTransition ( label::Label from, std::variant < string::Epsilon, alphabet::Symbol > input, label::Label to );
+	bool addTransition ( StateType from, std::variant < EpsilonType, SymbolType > input, StateType to );
 
 	/**
 	 * Adds transition defined by parameters to the automaton.
@@ -122,7 +129,7 @@ public:
 	 * @param next next state
 	 * @throws AutomatonException when transition already exists or when transition contains state or symbol not present in the automaton
 	 */
-	bool addTransition ( label::Label from, alphabet::Symbol input, label::Label to );
+	bool addTransition ( StateType from, SymbolType input, StateType to );
 
 	/**
 	 * Adds transition defined by parameters to the automaton.
@@ -130,66 +137,66 @@ public:
 	 * @param next next state
 	 * @throws AutomatonException when transition already exists or when transition contains state or symbol not present in the automaton
 	 */
-	bool addTransition ( label::Label from, label::Label to );
+	bool addTransition ( StateType from, StateType to );
 
 	/**
 	 * Removes transition from the automaton.
 	 * @param transition transition to remove
 	 * @throws AutomatonException when transition doesn't exists.
 	 */
-	bool removeTransition ( const label::Label & current, const alphabet::Symbol & input, const label::Label & next );
+	bool removeTransition ( const StateType & current, const SymbolType & input, const StateType & next );
 
 	/**
 	 * Removes transition from the automaton.
 	 * @param transition transition to remove
 	 * @throws AutomatonException when transition doesn't exists.
 	 */
-	bool removeTransition ( const label::Label & current, const label::Label & next );
+	bool removeTransition ( const StateType & current, const StateType & next );
 
 	/**
 	 * @return automaton transitions
 	 */
-	const std::map < std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > & getTransitions ( ) const;
+	const std::map < std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > & getTransitions ( ) const;
 
 	/**
 	 * @return automaton epsilon transitions
 	 */
-	std::map < label::Label, std::set < label::Label > > getEpsilonTransitions ( ) const;
+	std::map < StateType, std::set < StateType > > getEpsilonTransitions ( ) const;
 
 	/**
 	 * @return automaton transitions reading some symbol
 	 */
-	std::map < std::pair < label::Label, alphabet::Symbol >, std::set < label::Label > > getSymbolTransitions ( ) const;
+	std::map < std::pair < StateType, SymbolType >, std::set < StateType > > getSymbolTransitions ( ) const;
 
 	/**
 	 * @return automaton transitions from state
 	 */
-	std::map < std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > getTransitionsFromState ( const label::Label & from ) const;
+	std::map < std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > getTransitionsFromState ( const StateType & from ) const;
 
 	/**
 	 * @return automaton epsilon transitions from state
 	 */
-	std::map < label::Label, std::set < label::Label > > getEpsilonTransitionsFromState ( const label::Label & from ) const;
+	std::map < StateType, std::set < StateType > > getEpsilonTransitionsFromState ( const StateType & from ) const;
 
 	/**
 	 * @return automaton transitions from state reading some symbols
 	 */
-	std::map < std::pair < label::Label, alphabet::Symbol >, std::set < label::Label > > getSymbolTransitionsFromState ( const label::Label & from ) const;
+	std::map < std::pair < StateType, SymbolType >, std::set < StateType > > getSymbolTransitionsFromState ( const StateType & from ) const;
 
 	/**
 	 * @return automaton transitions to state
 	 */
-	std::map < std::pair < label::Label, std::variant < string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > getTransitionsToState ( const label::Label & from ) const;
+	std::map < std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > getTransitionsToState ( const StateType & from ) const;
 
 	/**
 	 * @return automaton epsilon transitions to state
 	 */
-	std::map < label::Label, std::set < label::Label > > getEpsilonTransitionsToState ( const label::Label & to ) const;
+	std::map < StateType, std::set < StateType > > getEpsilonTransitionsToState ( const StateType & to ) const;
 
 	/**
 	 * @return automaton transitions to state reading some symbols
 	 */
-	std::map < std::pair < label::Label, alphabet::Symbol >, std::set < label::Label > > getSymbolTransitionsToState ( const label::Label & to ) const;
+	std::map < std::pair < StateType, SymbolType >, std::set < StateType > > getSymbolTransitionsToState ( const StateType & to ) const;
 
 	/**
 	 * Determines whether NFA is without epsilon transitions.
@@ -240,77 +247,396 @@ public:
 	void composeTransitions ( std::deque < sax::Token > & out ) const;
 };
 
+template<class SymbolType, class EpsilonType, class StateType >
+EpsilonNFA < SymbolType, EpsilonType, StateType >::EpsilonNFA ( std::set < StateType > states, std::set < SymbolType > inputAlphabet, StateType initialState, std::set < StateType > finalStates ) : std::Components < EpsilonNFA, SymbolType, std::tuple < InputAlphabet >, std::tuple < >, StateType, std::tuple < States, FinalStates >, std::tuple < InitialState > > ( std::make_tuple ( std::move ( inputAlphabet ) ), std::tuple < > ( ), std::make_tuple ( std::move ( states ), std::move ( finalStates ) ), std::make_tuple ( std::move ( initialState ) ) ) {
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+EpsilonNFA < SymbolType, EpsilonType, StateType >::EpsilonNFA ( StateType initialState ) : EpsilonNFA ( std::set < StateType > { initialState }, std::set < SymbolType > { }, initialState, std::set < StateType > { } ) {
+}
+
+/* TODO
+template<class SymbolType, class EpsilonType, class StateType >
+EpsilonNFA < SymbolType, EpsilonType, StateType >::EpsilonNFA ( const MultiInitialStateNFA < > & other ) : EpsilonNFA ( other.getStates ( ) + std::set < StateType > { label::createUniqueLabel ( label::InitialStateLabel::INITIAL_STATE_LABEL, other.getStates ( ) ) }, other.getInputAlphabet ( ), label::createUniqueLabel ( label::InitialStateLabel::INITIAL_STATE_LABEL, other.getStates ( ) ), other.getFinalStates ( ) ) {
+	for ( const auto & transition : other.getTransitions ( ) ) {
+		std::pair < StateType, std::variant < EpsilonType, SymbolType > > key = std::make_pair ( transition.first.first, std::variant < EpsilonType, SymbolType > ( transition.first.second ) );
+		transitions[key] = transition.second;
+	}
+
+	std::pair < StateType, std::variant < EpsilonType, SymbolType > > key = std::make_pair ( this->getInitialState ( ), std::variant < EpsilonType, SymbolType > ( EpsilonType::EPSILON ) );
+	transitions[key] = other.getInitialStates ( );
+}
+*/
+
+template<class SymbolType, class EpsilonType, class StateType >
+EpsilonNFA < SymbolType, EpsilonType, StateType >::EpsilonNFA ( const NFA <> & other ) : EpsilonNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
+	for ( const auto & transition : other.getTransitions ( ) ) {
+		std::pair < StateType, std::variant < EpsilonType, SymbolType > > key = std::make_pair ( transition.first.first, std::variant < EpsilonType, SymbolType > ( transition.first.second ) );
+		transitions[key] = transition.second;
+	}
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+EpsilonNFA < SymbolType, EpsilonType, StateType >::EpsilonNFA ( const DFA<> & other ) : EpsilonNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
+	for ( const auto & transition : other.getTransitions ( ) ) {
+		std::pair < StateType, std::variant < EpsilonType, SymbolType > > key = std::make_pair ( transition.first.first, std::variant < EpsilonType, SymbolType > ( transition.first.second ) );
+		transitions[key].insert ( transition.second );
+	}
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+AutomatonBase * EpsilonNFA < SymbolType, EpsilonType, StateType >::clone ( ) const {
+	return new EpsilonNFA ( * this );
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+AutomatonBase * EpsilonNFA < SymbolType, EpsilonType, StateType >::plunder ( ) && {
+	return new EpsilonNFA ( std::move ( * this ) );
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+bool EpsilonNFA < SymbolType, EpsilonType, StateType >::addTransition ( StateType from, std::variant < EpsilonType, SymbolType > input, StateType to ) {
+	if ( !getStates ( ).count ( from ) )
+		throw AutomatonException ( "State \"" + std::to_string ( from ) + "\" doesn't exist." );
+
+	if ( input.template is < SymbolType > ( ) && !getInputAlphabet ( ).count ( input.template get < SymbolType > ( ) ) )
+		throw AutomatonException ( "Input symbol \"" + std::to_string ( input.template get < SymbolType > ( ) ) + "\" doesn't exist." );
+
+	if ( !getStates ( ).count ( to ) )
+		throw AutomatonException ( "State \"" + std::to_string ( to ) + "\" doesn't exist." );
+
+	std::pair < StateType, std::variant < EpsilonType, SymbolType > > key = std::make_pair ( std::move ( from ), std::move ( input ) );
+
+	return transitions[std::move ( key )].insert ( std::move ( to ) ).second;
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+bool EpsilonNFA < SymbolType, EpsilonType, StateType >::addTransition ( StateType from, SymbolType input, StateType to ) {
+	std::variant < EpsilonType, SymbolType > inputVariant ( std::move ( input ) );
+
+	return addTransition ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) );
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+bool EpsilonNFA < SymbolType, EpsilonType, StateType >::addTransition ( StateType from, StateType to ) {
+	std::variant < EpsilonType, SymbolType > inputVariant ( EpsilonType::EPSILON );
+
+	return addTransition ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) );
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+bool EpsilonNFA < SymbolType, EpsilonType, StateType >::removeTransition ( const StateType & from, const SymbolType & input, const StateType & to ) {
+	std::variant < EpsilonType, SymbolType > inputVariant ( input );
+	std::pair < StateType, std::variant < EpsilonType, SymbolType > > key = std::make_pair ( from, inputVariant );
+
+	return transitions[key].erase ( to );
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+bool EpsilonNFA < SymbolType, EpsilonType, StateType >::removeTransition ( const StateType & from, const StateType & to ) {
+	std::variant < EpsilonType, SymbolType > inputVariant ( EpsilonType::EPSILON );
+	std::pair < StateType, std::variant < EpsilonType, SymbolType > > key = std::make_pair ( from, inputVariant );
+
+	return transitions[key].erase ( to );
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+const std::map < std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > & EpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitions ( ) const {
+	return transitions;
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+std::map < StateType, std::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitions ( ) const {
+	std::map < StateType, std::set < StateType > > result;
+
+	for ( const std::pair < const std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > & transition : transitions )
+		if ( transition.first.second.template is < EpsilonType > ( ) )
+			result[transition.first.first].insert ( transition.second.begin ( ), transition.second.end ( ) );
+
+	return result;
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+std::map < std::pair < StateType, SymbolType >, std::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitions ( ) const {
+	std::map < std::pair < StateType, SymbolType >, std::set < StateType > > result;
+
+	for ( const std::pair < const std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > & transition : transitions )
+		if ( transition.first.second.template is < SymbolType > ( ) )
+			result[std::pair < StateType, SymbolType > ( transition.first.first, transition.first.second.template get < SymbolType > ( ) )].insert ( transition.second.begin ( ), transition.second.end ( ) );
+
+	return result;
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+std::map < std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitionsFromState ( const StateType & from ) const {
+	if ( !getStates ( ).count ( from ) )
+		throw AutomatonException ( "State \"" + std::to_string ( from ) + "\" doesn't exist" );
+
+	std::map < std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > transitionsFromState;
+
+	for ( const std::pair < const std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > & transition : transitions )
+		if ( transition.first.first == from )
+			transitionsFromState[transition.first].insert ( transition.second.begin ( ), transition.second.end ( ) );
+
+	return transitionsFromState;
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+std::map < StateType, std::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitionsFromState ( const StateType & from ) const {
+	if ( !getStates ( ).count ( from ) )
+		throw AutomatonException ( "State \"" + std::to_string ( from ) + "\" doesn't exist" );
+
+	std::pair < StateType, std::variant < EpsilonType, SymbolType > > key ( from, std::variant < EpsilonType, SymbolType > ( EpsilonType::EPSILON ) );
+	std::map < StateType, std::set < StateType > > res;
+	auto transition = transitions.find ( key );
+
+	if ( transition != transitions.end ( ) )
+		res.insert ( std::make_pair ( from, transition->second ) );
+
+	return res;
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+std::map < std::pair < StateType, SymbolType >, std::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitionsFromState ( const StateType & from ) const {
+	if ( !getStates ( ).count ( from ) )
+		throw AutomatonException ( "State \"" + std::to_string ( from ) + "\" doesn't exist" );
+
+	std::map < std::pair < StateType, SymbolType >, std::set < StateType > > transitionsFromState;
+
+	for ( const std::pair < const std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > & transition : transitions )
+		if ( ( transition.first.first == from ) && transition.first.second.template is < SymbolType > ( ) )
+			transitionsFromState[std::pair < StateType, SymbolType > ( transition.first.first, transition.first.second.template get < SymbolType > ( ) )].insert ( transition.second.begin ( ), transition.second.end ( ) );
+
+	return transitionsFromState;
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+std::map < std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitionsToState ( const StateType & to ) const {
+	if ( !getStates ( ).count ( to ) )
+		throw AutomatonException ( "State \"" + std::to_string ( to ) + "\" doesn't exist" );
+
+	std::map < std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > transitionsToState;
+
+	for ( const std::pair < const std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > & transition : transitions )
+		if ( transition.second.find ( to ) != transition.second.end ( ) )
+			transitionsToState[transition.first].insert ( transition.second.begin ( ), transition.second.end ( ) );
+
+	return transitionsToState;
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+std::map < StateType, std::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitionsToState ( const StateType & to ) const {
+	if ( !getStates ( ).count ( to ) )
+		throw AutomatonException ( "State \"" + std::to_string ( to ) + "\" doesn't exist" );
+
+	std::map < StateType, std::set < StateType > > transitionsToState;
+
+	for ( const std::pair < const std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > & transition : transitions )
+		if ( ( transition.second.find ( to ) != transition.second.end ( ) ) && transition.first.second.template is < EpsilonType > ( ) )
+			transitionsToState[transition.first.first].insert ( transition.second.begin ( ), transition.second.end ( ) );
+
+	return transitionsToState;
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+std::map < std::pair < StateType, SymbolType >, std::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitionsToState ( const StateType & to ) const {
+	if ( !getStates ( ).count ( to ) )
+		throw AutomatonException ( "State \"" + std::to_string ( to ) + "\" doesn't exist" );
+
+	std::map < std::pair < StateType, SymbolType >, std::set < StateType > > transitionsToState;
+
+	for ( const std::pair < const std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > & transition : transitions )
+		if ( ( transition.second.find ( to ) != transition.second.end ( ) ) && transition.first.second.template is < SymbolType > ( ) )
+			transitionsToState[std::pair < StateType, SymbolType > ( transition.first.first, transition.first.second.template get < SymbolType > ( ) )].insert ( transition.second.begin ( ), transition.second.end ( ) );
+
+	return transitionsToState;
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+bool EpsilonNFA < SymbolType, EpsilonType, StateType >::isEpsilonFree ( ) const {
+	for ( const std::pair < const std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > & transition : transitions )
+		if ( transition.first.second.template is < EpsilonType > ( ) )
+			return false;
+
+	return true;
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+bool EpsilonNFA < SymbolType, EpsilonType, StateType >::isDeterministic ( ) const {
+	for ( const std::pair < const std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > & transition : transitions )
+		if ( transition.second.size ( ) > 1 )
+			return false;
+
+	return isEpsilonFree ( );
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+bool EpsilonNFA < SymbolType, EpsilonType, StateType >::isTotal ( ) const {
+	return isDeterministic ( ) && transitions.size ( ) == getInputAlphabet ( ).size ( ) * getStates ( ).size ( );
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+int EpsilonNFA < SymbolType, EpsilonType, StateType >::compare ( const EpsilonNFA & other ) const {
+	auto first = std::tie ( getStates ( ), getInputAlphabet ( ), getInitialState ( ), getFinalStates ( ), transitions );
+	auto second = std::tie ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ), other.getTransitions ( ) );
+
+	std::compare < decltype ( first ) > comp;
+
+	return comp ( first, second );
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+void EpsilonNFA < SymbolType, EpsilonType, StateType >::operator >>( std::ostream & out ) const {
+	out << "(EpsilonNFA "
+	    << "states = " << getStates ( )
+	    << "inputAlphabet = " << getInputAlphabet ( )
+	    << "initialState = " << getInitialState ( )
+	    << "finalStates = " << getFinalStates ( )
+	    << "transitions = " << transitions
+	    << ")";
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+EpsilonNFA < SymbolType, EpsilonType, StateType >::operator std::string ( ) const {
+	std::stringstream ss;
+	ss << * this;
+	return ss.str ( );
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+EpsilonNFA < SymbolType, EpsilonType, StateType > EpsilonNFA < SymbolType, EpsilonType, StateType >::parse ( std::deque < sax::Token >::iterator & input ) {
+	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, EpsilonNFA::getXmlTagName() );
+
+	std::set < StateType > states = AutomatonFromXMLParser::parseStates < StateType > ( input );
+	std::set < SymbolType > inputSymbols = AutomatonFromXMLParser::parseInputAlphabet < SymbolType > ( input );
+	StateType initialState = AutomatonFromXMLParser::parseInitialState < StateType > ( input );
+	std::set < StateType > finalStates = AutomatonFromXMLParser::parseFinalStates < StateType > ( input );
+
+	EpsilonNFA < SymbolType, EpsilonType, StateType > automaton ( std::move ( initialState ) );
+
+	automaton.setStates ( std::move ( states ) );
+	automaton.setInputAlphabet ( std::move ( inputSymbols ) );
+	automaton.setFinalStates ( std::move ( finalStates ) );
+
+	AutomatonFromXMLParser::parseTransitions < EpsilonNFA > ( input, automaton );
+
+	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, EpsilonNFA::getXmlTagName() );
+	return automaton;
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+void EpsilonNFA < SymbolType, EpsilonType, StateType >::parseTransition ( std::deque < sax::Token >::iterator & input, EpsilonNFA & automaton ) {
+	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "transition" );
+	StateType from = AutomatonFromXMLParser::parseTransitionFrom < StateType > ( input );
+	std::variant < EpsilonType, SymbolType > inputVariant = AutomatonFromXMLParser::parseTransitionInputEpsilonSymbol < EpsilonType, SymbolType > ( input );
+	StateType to = AutomatonFromXMLParser::parseTransitionTo < StateType > ( input );
+	sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, "transition" );
+
+	automaton.addTransition ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) );
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+void EpsilonNFA < SymbolType, EpsilonType, StateType >::compose ( std::deque < sax::Token > & out ) const {
+	out.emplace_back ( EpsilonNFA::getXmlTagName(), sax::Token::TokenType::START_ELEMENT );
+
+	AutomatonToXMLComposer::composeStates ( out, this->getStates ( ) );
+	AutomatonToXMLComposer::composeInputAlphabet ( out, this->getInputAlphabet ( ) );
+	AutomatonToXMLComposer::composeInitialState ( out, this->getInitialState ( ) );
+	AutomatonToXMLComposer::composeFinalStates ( out, this->getFinalStates ( ) );
+	composeTransitions ( out );
+
+	out.emplace_back ( EpsilonNFA::getXmlTagName(), sax::Token::TokenType::END_ELEMENT );
+}
+
+template<class SymbolType, class EpsilonType, class StateType >
+void EpsilonNFA < SymbolType, EpsilonType, StateType >::composeTransitions ( std::deque < sax::Token > & out ) const {
+	out.emplace_back ( "transitions", sax::Token::TokenType::START_ELEMENT );
+
+	for ( const auto & transition : this->getTransitions ( ) )
+		for ( const auto & targetState : transition.second ) {
+			out.emplace_back ( "transition", sax::Token::TokenType::START_ELEMENT );
+
+			AutomatonToXMLComposer::composeTransitionFrom ( out, transition.first.first );
+			AutomatonToXMLComposer::composeTransitionInputEpsilonSymbol ( out, transition.first.second );
+			AutomatonToXMLComposer::composeTransitionTo ( out, targetState );
+
+			out.emplace_back ( "transition", sax::Token::TokenType::END_ELEMENT );
+		}
+
+	out.emplace_back ( "transitions", sax::Token::TokenType::END_ELEMENT );
+}
+
 } /* namespace automaton */
 
 namespace std {
 
-template < >
-class ComponentConstraint< automaton::EpsilonNFA, alphabet::Symbol, automaton::InputAlphabet > {
+template<class SymbolType, class EpsilonType, class StateType >
+class ComponentConstraint< automaton::EpsilonNFA < SymbolType, EpsilonType, StateType >, SymbolType, automaton::InputAlphabet > {
 public:
-	static bool used ( const automaton::EpsilonNFA & automaton, const alphabet::Symbol & symbol ) {
-		for ( const std::pair < const std::pair < label::Label, std::variant < ::string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > & transition : automaton.getTransitions ( ) )
-			if ( transition.first.second.is < alphabet::Symbol > ( ) && ( transition.first.second.get < alphabet::Symbol > ( ) == symbol ) )
+	static bool used ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & automaton, const SymbolType & symbol ) {
+		for ( const std::pair < const std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > & transition : automaton.getTransitions ( ) )
+			if ( transition.first.second.template is < SymbolType > ( ) && ( transition.first.second.template get < SymbolType > ( ) == symbol ) )
 				return true;
 
 		return false;
 	}
 
-	static bool available ( const automaton::EpsilonNFA &, const alphabet::Symbol & ) {
+	static bool available ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > &, const SymbolType & ) {
 		return true;
 	}
 
-	static void valid ( const automaton::EpsilonNFA &, const alphabet::Symbol & ) {
+	static void valid ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > &, const SymbolType & ) {
 	}
 };
 
-template < >
-class ComponentConstraint< automaton::EpsilonNFA, label::Label, automaton::States > {
+template<class SymbolType, class EpsilonType, class StateType >
+class ComponentConstraint< automaton::EpsilonNFA < SymbolType, EpsilonType, StateType >, StateType, automaton::States > {
 public:
-	static bool used ( const automaton::EpsilonNFA & automaton, const label::Label & state ) {
+	static bool used ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & automaton, const StateType & state ) {
 		if ( automaton.getInitialState ( ) == state )
 			return true;
 
 		if ( automaton.getFinalStates ( ).count ( state ) )
 			return true;
 
-		for ( const std::pair < const std::pair < label::Label, std::variant < ::string::Epsilon, alphabet::Symbol > >, std::set < label::Label > > & transition : automaton.getTransitions ( ) )
+		for ( const std::pair < const std::pair < StateType, std::variant < EpsilonType, SymbolType > >, std::set < StateType > > & transition : automaton.getTransitions ( ) )
 			if ( ( transition.first.first == state ) || transition.second.count ( state ) )
 				return true;
 
 		return false;
 	}
 
-	static bool available ( const automaton::EpsilonNFA &, const label::Label & ) {
+	static bool available ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > &, const StateType & ) {
 		return true;
 	}
 
-	static void valid ( const automaton::EpsilonNFA &, const label::Label & ) {
+	static void valid ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > &, const StateType & ) {
 	}
 };
 
-template < >
-class ComponentConstraint< automaton::EpsilonNFA, label::Label, automaton::FinalStates > {
+template<class SymbolType, class EpsilonType, class StateType >
+class ComponentConstraint< automaton::EpsilonNFA < SymbolType, EpsilonType, StateType >, StateType, automaton::FinalStates > {
 public:
-	static bool used ( const automaton::EpsilonNFA &, const label::Label & ) {
+	static bool used ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > &, const StateType & ) {
 		return false;
 	}
 
-	static bool available ( const automaton::EpsilonNFA & automaton, const label::Label & state ) {
-		return automaton.accessComponent < automaton::States > ( ).get ( ).count ( state );
+	static bool available ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & automaton, const StateType & state ) {
+		return automaton.template accessComponent < automaton::States > ( ).get ( ).count ( state );
 	}
 
-	static void valid ( const automaton::EpsilonNFA &, const label::Label & ) {
+	static void valid ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > &, const StateType & ) {
 	}
 };
 
-template < >
-class ElementConstraint< automaton::EpsilonNFA, label::Label, automaton::InitialState > {
+template<class SymbolType, class EpsilonType, class StateType >
+class ElementConstraint< automaton::EpsilonNFA < SymbolType, EpsilonType, StateType >, StateType, automaton::InitialState > {
 public:
-	static bool available ( const automaton::EpsilonNFA & automaton, const label::Label & state ) {
-		return automaton.accessComponent < automaton::States > ( ).get ( ).count ( state );
+	static bool available ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & automaton, const StateType & state ) {
+		return automaton.template accessComponent < automaton::States > ( ).get ( ).count ( state );
 	}
 
-	static void valid ( const automaton::EpsilonNFA &, const label::Label & ) {
+	static void valid ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > &, const StateType & ) {
 	}
 };
 
diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.cpp b/alib2data/src/automaton/FSM/ExtendedNFA.cpp
index 2eed9f4363ca1d03f2602b24a0e53fd98bbbc852..49237ccfaf46ead47a210b9ff32e9bffff91c94d 100644
--- a/alib2data/src/automaton/FSM/ExtendedNFA.cpp
+++ b/alib2data/src/automaton/FSM/ExtendedNFA.cpp
@@ -40,7 +40,7 @@ ExtendedNFA::ExtendedNFA ( const CompactNFA < > & other ) : ExtendedNFA ( other.
 	}
 }
 
-ExtendedNFA::ExtendedNFA ( const EpsilonNFA & other ) : ExtendedNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
+ExtendedNFA::ExtendedNFA ( const EpsilonNFA < > & other ) : ExtendedNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
 	for ( const auto & transition : other.getTransitions ( ) ) {
 		if ( transition.first.second.is < string::Epsilon > ( ) ) {
 			std::pair < label::Label, regexp::RegExp > key = std::make_pair ( transition.first.first, regexp::RegExp ( regexp::regexpFrom ( ) ) );
@@ -232,7 +232,7 @@ auto extendedNFAParserRegister2 = xmlApi < alib::Object >::ParserRegister < auto
 auto ExtendedNFAFromDFA = castApi::CastRegister < automaton::ExtendedNFA, automaton::DFA < > > ( );
 auto ExtendedNFAFromNFA = castApi::CastRegister < automaton::ExtendedNFA, automaton::NFA < > > ( );
 auto ExtendedNFAFromMultiInitialStateNFA = castApi::CastRegister < automaton::ExtendedNFA, automaton::MultiInitialStateNFA < > > ( );
-auto ExtendedNFAEpsilonNFA = castApi::CastRegister < automaton::ExtendedNFA, automaton::EpsilonNFA > ( );
+auto ExtendedNFAEpsilonNFA = castApi::CastRegister < automaton::ExtendedNFA, automaton::EpsilonNFA < > > ( );
 auto ExtendedNFACompactNFA = castApi::CastRegister < automaton::ExtendedNFA, automaton::CompactNFA < > > ( );
 auto ExtendedNFACastBinder = castApi::CastPoolStringBinder < automaton::ExtendedNFA > ( automaton::ExtendedNFA::getXmlTagName() );
 
diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.h b/alib2data/src/automaton/FSM/ExtendedNFA.h
index 8bb5fe299f2286d902c42820ba96599997b1ac23..8cf10ca94196739a7212b3e1c83305fba9393704 100644
--- a/alib2data/src/automaton/FSM/ExtendedNFA.h
+++ b/alib2data/src/automaton/FSM/ExtendedNFA.h
@@ -39,7 +39,7 @@ public:
 	explicit ExtendedNFA ( label::Label initialState );
 	explicit ExtendedNFA ( std::set < label::Label > states, std::set < alphabet::Symbol > inputAlphabet, label::Label initialState, std::set < label::Label > finalStates );
 	explicit ExtendedNFA ( const CompactNFA < > & other );
-	explicit ExtendedNFA ( const EpsilonNFA & other );
+	explicit ExtendedNFA ( const EpsilonNFA < > & other );
 	explicit ExtendedNFA ( const MultiInitialStateNFA < > & other );
 	explicit ExtendedNFA ( const NFA<> & other );
 	explicit ExtendedNFA ( const DFA<> & other );
diff --git a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp
index bf6a1302d4dc84ed0948489f68cbd6d9b2e2256f..299216e099530b21da20550a74e1a5ced653dd93 100644
--- a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp
+++ b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp
@@ -41,7 +41,7 @@ void process(const std::map<label::Label, std::set<label::Label>>& epsilonTransi
 	}
 }
 
-std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::EpsilonNFA & fsm) {
+std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::EpsilonNFA < > & fsm) {
 	std::map<label::Label, std::set<label::Label>> res;
 
 	for(const label::Label& state : fsm.getStates())
@@ -65,7 +65,7 @@ std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClos
 	return res;
 }
 
-auto AllEpsilonClosureEpsilonNFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::EpsilonNFA>(AllEpsilonClosure::allEpsilonClosure);
+auto AllEpsilonClosureEpsilonNFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::EpsilonNFA < > >(AllEpsilonClosure::allEpsilonClosure);
 
 std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::MultiInitialStateNFA < > & fsm) {
 	std::map<label::Label, std::set<label::Label>> closure;
diff --git a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h
index 30fc1c18ef22a461be4986be80c975c531ac573f..ec18263362ded39bc5d496e6c8680f924b404046 100644
--- a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h
+++ b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h
@@ -30,7 +30,7 @@ public:
 	/**
 	 * Computes allEpsilon closure of a state in allEpsilon nonfree automaton
 	 */
-	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::EpsilonNFA & fsm);
+	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::EpsilonNFA < > & fsm);
 	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::MultiInitialStateNFA < > & fsm);
 	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::NFA < > & fsm);
 	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::DFA < > & fsm);
diff --git a/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp b/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp
index 7ff7e93deee7cfc827f2ca074e4579fb7d588807..3356f628231ba5320be8f80e2e684dd1e5c38171 100644
--- a/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp
+++ b/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp
@@ -49,7 +49,7 @@ std::set<label::Label> ReachableStates::reachableStates( const T & fsm ) {
 	return visited;
 }
 
-auto ReachableStatesEpsilonNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::EpsilonNFA>(ReachableStates::reachableStates);
+auto ReachableStatesEpsilonNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::EpsilonNFA < > >(ReachableStates::reachableStates);
 auto ReachableStatesNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::NFA < > >(ReachableStates::reachableStates);
 auto ReachableStatesCompactNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::CompactNFA < > >(ReachableStates::reachableStates);
 auto ReachableStatesExtendedNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::ExtendedNFA>(ReachableStates::reachableStates);
diff --git a/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp b/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp
index f0225e857b8434bd8c9cd9b076fd8bf896ef0607..d922e099ad7890a796e3e6fe9e18473daa97c3bb 100644
--- a/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp
+++ b/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp
@@ -50,7 +50,7 @@ std::set<label::Label> UsefullStates::usefullStates( const T & fsm ) {
 	return visited;
 }
 
-auto UsefullStatesEpsilonNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::EpsilonNFA>(UsefullStates::usefullStates);
+auto UsefullStatesEpsilonNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::EpsilonNFA < > >(UsefullStates::usefullStates);
 auto UsefullStatesNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::NFA < > >(UsefullStates::usefullStates);
 auto UsefullStatesCompactNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::CompactNFA < > >(UsefullStates::usefullStates);
 auto UsefullStatesExtendedNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::ExtendedNFA>(UsefullStates::usefullStates);
diff --git a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.cpp b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.cpp
index 954f49e7462f208a7f34619a849c471a6f0ecd72..53013101738f9d5bbfc5cde54feee9cddc73bfde 100644
--- a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.cpp
+++ b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.cpp
@@ -34,7 +34,7 @@ automaton::NFA < > EpsilonRemoverIncoming::remove(const automaton::NFA < > & ori
 
 auto EpsilonRemoverIncomingNFA = EpsilonRemoverIncoming::RegistratorWrapper<automaton::NFA < > , automaton::NFA < > >(EpsilonRemoverIncoming::remove);
 
-automaton::NFA < > EpsilonRemoverIncoming::remove( const automaton::EpsilonNFA & origFSM ) {
+automaton::NFA < > EpsilonRemoverIncoming::remove( const automaton::EpsilonNFA < > & origFSM ) {
 	automaton::NFA < > fsm(origFSM.getInitialState());
 
 	fsm.setStates( origFSM.getStates() );
@@ -74,7 +74,7 @@ automaton::NFA < > EpsilonRemoverIncoming::remove( const automaton::EpsilonNFA &
 	return fsm;
 }
 
-auto EpsilonRemoverIncomingEpsilonNFA = EpsilonRemoverIncoming::RegistratorWrapper<automaton::NFA < > , automaton::EpsilonNFA>(EpsilonRemoverIncoming::remove);
+auto EpsilonRemoverIncomingEpsilonNFA = EpsilonRemoverIncoming::RegistratorWrapper<automaton::NFA < > , automaton::EpsilonNFA < > >(EpsilonRemoverIncoming::remove);
 
 automaton::Automaton EpsilonRemoverIncoming::remove(const automaton::Automaton& automaton) {
 	return dispatch(automaton.getData());
diff --git a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.h b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.h
index 02d41d019782341440a0ce8447c46d47f1afc4a1..8b1358cc47dd47fd84b129394bb1f25dc4c47f21 100644
--- a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.h
+++ b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.h
@@ -32,7 +32,7 @@ public:
 	/**
 	 * Computes epsilon closure of a state in epsilon nonfree automaton
 	 */
-	static automaton::NFA < > remove( const automaton::EpsilonNFA & fsm );
+	static automaton::NFA < > remove( const automaton::EpsilonNFA < > & fsm );
 	static automaton::MultiInitialStateNFA < > remove( const automaton::MultiInitialStateNFA < > & fsm );
 	static automaton::NFA < > remove( const automaton::NFA < > & fsm );
 	static automaton::DFA<> remove( const automaton::DFA<> & fsm );
diff --git a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.cpp b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.cpp
index 1ae00df98db5b3ae349d056caf95d66dc50412fe..9307450b6d4b98f2e211f5d5829d652989092176 100644
--- a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.cpp
+++ b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.cpp
@@ -34,7 +34,7 @@ automaton::NFA < > EpsilonRemoverOutgoing::remove(const automaton::NFA < > & ori
 
 auto EpsilonRemoverOutgoingNFA = EpsilonRemoverOutgoing::RegistratorWrapper<automaton::NFA < > , automaton::NFA < > >(EpsilonRemoverOutgoing::remove);
 
-automaton::MultiInitialStateNFA < > EpsilonRemoverOutgoing::remove( const automaton::EpsilonNFA & origFSM ) {
+automaton::MultiInitialStateNFA < > EpsilonRemoverOutgoing::remove( const automaton::EpsilonNFA < > & origFSM ) {
 	automaton::MultiInitialStateNFA < > fsm;
 	fsm.setStates( origFSM.getStates() );
 	fsm.setFinalStates( origFSM.getFinalStates() );
@@ -58,7 +58,7 @@ automaton::MultiInitialStateNFA < > EpsilonRemoverOutgoing::remove( const automa
 	return fsm;
 }
 
-auto EpsilonRemoverOutgoingEpsilonNFA = EpsilonRemoverOutgoing::RegistratorWrapper<automaton::MultiInitialStateNFA < >, automaton::EpsilonNFA>(EpsilonRemoverOutgoing::remove);
+auto EpsilonRemoverOutgoingEpsilonNFA = EpsilonRemoverOutgoing::RegistratorWrapper<automaton::MultiInitialStateNFA < >, automaton::EpsilonNFA < > >(EpsilonRemoverOutgoing::remove);
 
 automaton::Automaton EpsilonRemoverOutgoing::remove(const automaton::Automaton& automaton) {
 	return dispatch(automaton.getData());
diff --git a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.h b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.h
index 5b8252443a4b84303e4edbd485b1bfc343cd8ead..9d17b7b4bf73d096013aaecda5a7a19cf3630995 100644
--- a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.h
+++ b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.h
@@ -32,7 +32,7 @@ public:
 	/**
 	 * Computes epsilon closure of a state in epsilon nonfree automaton
 	 */
-	static automaton::MultiInitialStateNFA < > remove( const automaton::EpsilonNFA & fsm );
+	static automaton::MultiInitialStateNFA < > remove( const automaton::EpsilonNFA < > & fsm );
 	static automaton::MultiInitialStateNFA < > remove( const automaton::MultiInitialStateNFA < > & fsm );
 	static automaton::NFA < > remove( const automaton::NFA < > & fsm );
 	static automaton::DFA<> remove( const automaton::DFA<> & fsm );
diff --git a/alib2elgo/src/automaton/simplify/efficient/Trim.cpp b/alib2elgo/src/automaton/simplify/efficient/Trim.cpp
index 19cc547d78bc7bc324836cdc7b79de1f63e0e6a2..a638881a295db6f251bf8a79eff7d1f22d035ec6 100644
--- a/alib2elgo/src/automaton/simplify/efficient/Trim.cpp
+++ b/alib2elgo/src/automaton/simplify/efficient/Trim.cpp
@@ -31,7 +31,7 @@ T Trim::trim( const T & fsm ) {
 auto TrimDFA = Trim::RegistratorWrapper<automaton::DFA<>, automaton::DFA<>>(Trim::trim);
 auto TrimNFA = Trim::RegistratorWrapper<automaton::NFA < > , automaton::NFA < > >(Trim::trim);
 auto TrimMultiInitialStateNFA = Trim::RegistratorWrapper<automaton::MultiInitialStateNFA < >, automaton::MultiInitialStateNFA < >>(Trim::trim);
-auto TrimEpsilonNFA = Trim::RegistratorWrapper<automaton::EpsilonNFA, automaton::EpsilonNFA>(Trim::trim);
+auto TrimEpsilonNFA = Trim::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::EpsilonNFA < > >(Trim::trim);
 auto TrimCompactNFA = Trim::RegistratorWrapper<automaton::CompactNFA < >, automaton::CompactNFA < > >(Trim::trim);
 auto TrimExtendedNFA = Trim::RegistratorWrapper<automaton::ExtendedNFA, automaton::ExtendedNFA>(Trim::trim);
 
diff --git a/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.cpp b/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.cpp
index 968d3affa60612d6c4fe1010e0838602b6b1580b..c7f6b19eb25bf8e066553080264ddd709100c91a 100644
--- a/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.cpp
+++ b/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.cpp
@@ -51,7 +51,7 @@ T UnreachableStatesRemover::remove( const T & fsm ) {
 	return M;
 }
 
-auto UnreachableStatesRemoverEpsilonNFA = UnreachableStatesRemover::RegistratorWrapper<automaton::EpsilonNFA, automaton::EpsilonNFA>(UnreachableStatesRemover::remove);
+auto UnreachableStatesRemoverEpsilonNFA = UnreachableStatesRemover::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::EpsilonNFA < > >(UnreachableStatesRemover::remove);
 auto UnreachableStatesRemoverNFA = UnreachableStatesRemover::RegistratorWrapper<automaton::NFA < > , automaton::NFA < > >(UnreachableStatesRemover::remove);
 auto UnreachableStatesRemoverCompactNFA = UnreachableStatesRemover::RegistratorWrapper<automaton::CompactNFA < >, automaton::CompactNFA < > >(UnreachableStatesRemover::remove);
 auto UnreachableStatesRemoverExtendedNFA = UnreachableStatesRemover::RegistratorWrapper<automaton::ExtendedNFA, automaton::ExtendedNFA>(UnreachableStatesRemover::remove);
diff --git a/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.cpp b/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.cpp
index 538cb956c16f3429269eabccc1a11f351de026aa..e87376c70199e9101553007aacd3afb633a346a3 100644
--- a/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.cpp
+++ b/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.cpp
@@ -53,7 +53,7 @@ T UselessStatesRemover::remove( const T & fsm ) {
 	return M;
 }
 
-auto UselessStatesRemoverEpsilonNFA = UselessStatesRemover::RegistratorWrapper<automaton::EpsilonNFA, automaton::EpsilonNFA>(UselessStatesRemover::remove);
+auto UselessStatesRemoverEpsilonNFA = UselessStatesRemover::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::EpsilonNFA < > >(UselessStatesRemover::remove);
 auto UselessStatesRemoverNFA = UselessStatesRemover::RegistratorWrapper<automaton::NFA < > , automaton::NFA < > >(UselessStatesRemover::remove);
 auto UselessStatesRemoverCompactNFA = UselessStatesRemover::RegistratorWrapper<automaton::CompactNFA < >, automaton::CompactNFA < > >(UselessStatesRemover::remove);
 auto UselessStatesRemoverExtendedNFA = UselessStatesRemover::RegistratorWrapper<automaton::ExtendedNFA, automaton::ExtendedNFA>(UselessStatesRemover::remove);
diff --git a/alib2str/src/automaton/AutomatonFromStringParser.cpp b/alib2str/src/automaton/AutomatonFromStringParser.cpp
index 3c5422df2d7c6d6964826d2bbf5ed262ee107c27..ad01bbb3b3383b6a51e4e4597f654a9d4053db31 100644
--- a/alib2str/src/automaton/AutomatonFromStringParser.cpp
+++ b/alib2str/src/automaton/AutomatonFromStringParser.cpp
@@ -45,7 +45,7 @@ Automaton AutomatonFromStringParser::parseAutomaton(std::istream& input, const s
 	}
 }
 
-EpsilonNFA AutomatonFromStringParser::parseEpsilonNFA(std::istream& input) const {
+EpsilonNFA < > AutomatonFromStringParser::parseEpsilonNFA(std::istream& input) const {
 	AutomatonFromStringLexer::Token token = m_AutomatonLexer.next(input);
 	if(token.type != AutomatonFromStringLexer::TokenType::EPSILON_NFA) {
 		throw exception::CommonException("Unrecognised ENFA token.");
@@ -88,7 +88,7 @@ EpsilonNFA AutomatonFromStringParser::parseEpsilonNFA(std::istream& input) const
 
 	if(initialState == NULL) throw exception::CommonException("No initial state recognised.");
 
-	EpsilonNFA res(*initialState);
+	EpsilonNFA < > res(*initialState);
 	delete initialState;
 
 	for(const std::variant<string::Epsilon, alphabet::Symbol> inputSymbol : symbols) {
diff --git a/alib2str/src/automaton/AutomatonFromStringParser.h b/alib2str/src/automaton/AutomatonFromStringParser.h
index b67ce2f17fe7da827d5065585c7402b55c27216a..e15e42a5333cf3e67c71280533845eedcc1ac306 100644
--- a/alib2str/src/automaton/AutomatonFromStringParser.h
+++ b/alib2str/src/automaton/AutomatonFromStringParser.h
@@ -46,7 +46,7 @@ private:
 	Automaton parseAutomaton(std::istream& input) const;
 	Automaton parseAutomaton(std::istream& input, const std::set<FEATURES>& features) const;
 
-	EpsilonNFA parseEpsilonNFA(std::istream& input) const;
+	EpsilonNFA<> parseEpsilonNFA(std::istream& input) const;
 	NFA<> parseNFA(std::istream& input) const;
 	MultiInitialStateNFA<> parseMultiInitialStateNFA(std::istream& input) const;
 	DFA<> parseDFA(std::istream& input) const;
diff --git a/alib2str/src/automaton/AutomatonToStringComposer.cpp b/alib2str/src/automaton/AutomatonToStringComposer.cpp
index e48c3d8fd642ecaf4c56bb39b9cfe19647286cac..a39ea164cd3ffc64b5b35185620e80220f963d7a 100644
--- a/alib2str/src/automaton/AutomatonToStringComposer.cpp
+++ b/alib2str/src/automaton/AutomatonToStringComposer.cpp
@@ -66,7 +66,7 @@ void AutomatonToStringComposer::composeTransitionsFromState(std::ostream& out, c
 	}
 }
 
-void AutomatonToStringComposer::composeTransitionsFromState(std::ostream& out, const EpsilonNFA& automaton, const label::Label& from) {
+void AutomatonToStringComposer::composeTransitionsFromState(std::ostream& out, const EpsilonNFA < > & automaton, const label::Label& from) {
 	std::map<std::pair<label::Label, alphabet::Symbol>, std::set<label::Label> > symbolTransitionsFromState = automaton.getSymbolTransitionsFromState(from);
 
 	for(const alphabet::Symbol& inputSymbol : automaton.getInputAlphabet()) {
@@ -174,7 +174,7 @@ void AutomatonToStringComposer::compose(std::ostream& out, const MultiInitialSta
 
 AutomatonToStringComposer::RegistratorWrapper<void, MultiInitialStateNFA < > > AutomatonToStringComposerMultiInitialStateNFA = AutomatonToStringComposer::RegistratorWrapper<void, MultiInitialStateNFA < > >(AutomatonToStringComposer::compose);
 
-void AutomatonToStringComposer::compose(std::ostream& out, const EpsilonNFA& automaton) {
+void AutomatonToStringComposer::compose(std::ostream& out, const EpsilonNFA < > & automaton) {
 	out << "ENFA";
 	for(const auto& symbol : automaton.getInputAlphabet()) {
 		out << " ";
@@ -199,7 +199,7 @@ void AutomatonToStringComposer::compose(std::ostream& out, const EpsilonNFA& aut
 	}
 }
 
-AutomatonToStringComposer::RegistratorWrapper<void, EpsilonNFA> AutomatonToStringComposerEpsilonNFA = AutomatonToStringComposer::RegistratorWrapper<void, EpsilonNFA>(AutomatonToStringComposer::compose);
+AutomatonToStringComposer::RegistratorWrapper<void, EpsilonNFA < > > AutomatonToStringComposerEpsilonNFA = AutomatonToStringComposer::RegistratorWrapper<void, EpsilonNFA < > >(AutomatonToStringComposer::compose);
 
 void AutomatonToStringComposer::compose(std::ostream& output, const Automaton& automaton) {
 	dispatch(output, automaton.getData());
diff --git a/alib2str/src/automaton/AutomatonToStringComposer.h b/alib2str/src/automaton/AutomatonToStringComposer.h
index 5abd739f29a15937cecf685c47a6bbf40af7434d..9d39f4d7890cccb22ebcfab014d757a24bb1cf59 100644
--- a/alib2str/src/automaton/AutomatonToStringComposer.h
+++ b/alib2str/src/automaton/AutomatonToStringComposer.h
@@ -20,7 +20,7 @@ class AutomatonToStringComposer : public std::SingleDispatchFirstStaticParam<Aut
 	static void composeTransitionsFromState(std::ostream& out, const DFA < > & automaton, const label::Label& from);
 	static void composeTransitionsFromState(std::ostream& out, const NFA < > & automaton, const label::Label& from);
 	static void composeTransitionsFromState(std::ostream& out, const MultiInitialStateNFA < > & automaton, const label::Label& from);
-	static void composeTransitionsFromState(std::ostream& out, const EpsilonNFA& automaton, const label::Label& from);
+	static void composeTransitionsFromState(std::ostream& out, const EpsilonNFA < > & automaton, const label::Label& from);
 
 public:
 	/**
@@ -33,7 +33,7 @@ public:
 	static void compose(std::ostream& output, const DFA < > & automaton);
 	static void compose(std::ostream& output, const NFA < > & automaton);
 	static void compose(std::ostream& output, const MultiInitialStateNFA < > & automaton);
-	static void compose(std::ostream& output, const EpsilonNFA& automaton);
+	static void compose(std::ostream& output, const EpsilonNFA < > & automaton);
 };
 
 } /* namespace automaton */