From 62add5389d4537497f3dbc844f91c7a3e84e10c2 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Tue, 11 Oct 2016 15:12:57 +0200
Subject: [PATCH] template NFTA automaton

---
 acompare2/src/AutomatonCompare.cpp            |   8 +-
 acompare2/src/AutomatonCompare.h              |   6 +-
 aconvert2/src/DotConverter.cpp                |   6 +-
 aconvert2/src/DotConverter.h                  |   4 +-
 aconvert2/src/GasTexConverter.cpp             |   6 +-
 aconvert2/src/GasTexConverter.h               |   4 +-
 aconvert2/src/TikZConverter.cpp               |   6 +-
 aconvert2/src/TikZConverter.h                 |   4 +-
 .../exact/ExactPatternMatchingAutomaton.cpp   |  12 +-
 .../exact/ExactPatternMatchingAutomaton.h     |   4 +-
 .../exact/ExactSubtreeMatchingAutomaton.cpp   |   8 +-
 .../exact/ExactSubtreeMatchingAutomaton.h     |   2 +-
 .../src/automaton/determinize/Determinize.h   |   2 +-
 .../determinize/DeterminizeNFTAPart.cxx       |   6 +-
 alib2algo/src/automaton/run/Accept.cpp        |   4 +-
 alib2algo/src/automaton/run/Accept.h          |   2 +-
 alib2algo/src/automaton/run/Run.cpp           |   4 +-
 alib2algo/src/automaton/run/Run.h             |   4 +-
 .../automaton/determinize/determinizeTest.cpp |   2 +-
 alib2data/src/automaton/AutomatonFeatures.h   |   1 +
 alib2data/src/automaton/TA/NFTA.cpp           | 154 +---------
 alib2data/src/automaton/TA/NFTA.h             | 279 ++++++++++++++----
 .../test-src/automaton/AutomatonTest.cpp      |   6 +-
 23 files changed, 276 insertions(+), 258 deletions(-)

diff --git a/acompare2/src/AutomatonCompare.cpp b/acompare2/src/AutomatonCompare.cpp
index b2d48528cb..2b2316c638 100644
--- a/acompare2/src/AutomatonCompare.cpp
+++ b/acompare2/src/AutomatonCompare.cpp
@@ -93,7 +93,7 @@ bool AutomatonCompare::testCompare(const automaton::DFTA < > & a, const automato
 			a.getTransitions()    == b.getTransitions()    ;
 }
 
-bool AutomatonCompare::testCompare(const automaton::NFTA& a, const automaton::NFTA& b) {
+bool AutomatonCompare::testCompare(const automaton::NFTA < > & a, const automaton::NFTA < > & b) {
 	return  	a.getFinalStates()    == b.getFinalStates()    &&
 //			a.getInputAlphabet()  == b.getInputAlphabet()  &&
 			a.getStates()         == b.getStates()         &&
@@ -514,7 +514,7 @@ void AutomatonCompare::printCompare(const automaton::DFTA < > & a, const automat
 	}
 }
 
-void AutomatonCompare::printCompare(const automaton::NFTA& a, const automaton::NFTA& b) {
+void AutomatonCompare::printCompare(const automaton::NFTA < > & a, const automaton::NFTA < > & b) {
 	std::cout << "AutomatonCompareer" << std::endl;
 
 	if(a.getFinalStates() != b.getFinalStates()){
@@ -1249,7 +1249,7 @@ int AutomatonCompare::compare(const automaton::DFTA < > & a, const automaton::DF
 
 auto AutomatonCompareDFTA = AutomatonCompare::RegistratorWrapper<int, automaton::DFTA < >, automaton::DFTA < > >(AutomatonCompare::compare);
 
-int AutomatonCompare::compare(const automaton::NFTA& a, const automaton::NFTA& b) {
+int AutomatonCompare::compare(const automaton::NFTA < > & a, const automaton::NFTA < > & b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
 	  return 1;
@@ -1258,7 +1258,7 @@ int AutomatonCompare::compare(const automaton::NFTA& a, const automaton::NFTA& b
 	}
 }
 
-auto AutomatonCompareNFTA = AutomatonCompare::RegistratorWrapper<int, automaton::NFTA, automaton::NFTA>(AutomatonCompare::compare);
+auto AutomatonCompareNFTA = AutomatonCompare::RegistratorWrapper<int, automaton::NFTA < >, automaton::NFTA < > >(AutomatonCompare::compare);
 
 int AutomatonCompare::compare(const automaton::DPDA < > & a, const automaton::DPDA < > & b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
diff --git a/acompare2/src/AutomatonCompare.h b/acompare2/src/AutomatonCompare.h
index 5f71a24885..10fdcc9afa 100644
--- a/acompare2/src/AutomatonCompare.h
+++ b/acompare2/src/AutomatonCompare.h
@@ -47,8 +47,8 @@ private:
 	static bool testCompare(const automaton::DFTA < > & a, const automaton::DFTA < > & b);
 	static void printCompare(const automaton::DFTA < > & a, const automaton::DFTA < > & b);
 
-	static bool testCompare(const automaton::NFTA& a, const automaton::NFTA& b);
-	static void printCompare(const automaton::NFTA& a, const automaton::NFTA& b);
+	static bool testCompare(const automaton::NFTA < > & a, const automaton::NFTA < > & b);
+	static void printCompare(const automaton::NFTA < > & a, const automaton::NFTA < > & b);
 
 	static bool testCompare(const automaton::InputDrivenDPDA < > & a, const automaton::InputDrivenDPDA < > & b);
 	static void printCompare(const automaton::InputDrivenDPDA < > & a, const automaton::InputDrivenDPDA < > & b);
@@ -89,7 +89,7 @@ public:
 	static int compare(const automaton::CompactNFA < > & a, const automaton::CompactNFA < > & b);
 
 	static int compare(const automaton::DFTA < > & a, const automaton::DFTA < > & b);
-	static int compare(const automaton::NFTA& a, const automaton::NFTA& b);
+	static int compare(const automaton::NFTA < > & a, const automaton::NFTA < > & b);
 
 	static int compare(const automaton::DPDA < > & a, const automaton::DPDA < > & b);
 	static int compare(const automaton::NPDA < > & a, const automaton::NPDA < > & b);
diff --git a/aconvert2/src/DotConverter.cpp b/aconvert2/src/DotConverter.cpp
index 7deeb1d51d..a00f17aff5 100644
--- a/aconvert2/src/DotConverter.cpp
+++ b/aconvert2/src/DotConverter.cpp
@@ -250,7 +250,7 @@ void DotConverter::convert(std::ostream& out, const automaton::CompactNFA < > &
 
 auto DotConverterCompactNFA = DotConverter::RegistratorWrapper<void, automaton::CompactNFA < > >(DotConverter::convert);
 
-void DotConverter::convert(std::ostream& out, const automaton::NFTA& a) {
+void DotConverter::convert(std::ostream& out, const automaton::NFTA < > & a) {
 	out << "digraph automaton {\n";
 	out << "rankdir=LR;\n";
 	int cnt = 1;
@@ -277,7 +277,7 @@ void DotConverter::convert(std::ostream& out, const automaton::NFTA& a) {
 	out << "}";
 }
 
-auto DotConverterNFTA = DotConverter::RegistratorWrapper<void, automaton::NFTA>(DotConverter::convert);
+auto DotConverterNFTA = DotConverter::RegistratorWrapper<void, automaton::NFTA < > >(DotConverter::convert);
 
 void DotConverter::convert(std::ostream& out, const automaton::DFTA < > & a) {
 	out << "digraph automaton {\n";
@@ -882,7 +882,7 @@ void DotConverter::transitions(const automaton::CompactNFA < > & fsm, const std:
 	}
 }
 
-void DotConverter::transitions(const automaton::NFTA& fta, const std::map<label::Label, int>& states, std::ostream& out) {
+void DotConverter::transitions(const automaton::NFTA < > & fta, const std::map<label::Label, int>& states, std::ostream& out) {
 	std::map<std::pair<int, std::vector<int>>, std::string> transitions;
 
 	//put transitions from automaton to "transitions"
diff --git a/aconvert2/src/DotConverter.h b/aconvert2/src/DotConverter.h
index 677b4917cf..20d2ef38b1 100644
--- a/aconvert2/src/DotConverter.h
+++ b/aconvert2/src/DotConverter.h
@@ -26,7 +26,7 @@ class DotConverter : public std::SingleDispatchFirstStaticParam<DotConverter, vo
 	static void transitions(const automaton::DFA<>& fsm, const std::map<label::Label, int>& states, std::ostream& out);
 	static void transitions(const automaton::ExtendedNFA& fsm, const std::map<label::Label, int>& states, std::ostream& out);
 	static void transitions(const automaton::CompactNFA < > & fsm, const std::map<label::Label, int>& states, std::ostream& out);
-	static void transitions(const automaton::NFTA& fsm, const std::map<label::Label, int>& states, std::ostream& out);
+	static void transitions(const automaton::NFTA < > & fsm, const std::map<label::Label, int>& states, std::ostream& out);
 	static void transitions(const automaton::DFTA < > & fsm, const std::map<label::Label, int>& states, std::ostream& out);
 	static void transitions(const automaton::DPDA < > & pda, const std::map<label::Label, int>& states, std::ostream& out);
 	static void transitions(const automaton::SinglePopDPDA < > & tm, const std::map<label::Label, int>& states, std::ostream& out);
@@ -48,7 +48,7 @@ public:
 	static void convert(std::ostream& out, const automaton::DFA<>& a);
 	static void convert(std::ostream& out, const automaton::ExtendedNFA& a);
 	static void convert(std::ostream& out, const automaton::CompactNFA < > & a);
-	static void convert(std::ostream& out, const automaton::NFTA& a);
+	static void convert(std::ostream& out, const automaton::NFTA < > & a);
 	static void convert(std::ostream& out, const automaton::DFTA < > & a);
 	static void convert(std::ostream& out, const automaton::DPDA < > & a);
 	static void convert(std::ostream& out, const automaton::SinglePopDPDA < > & a);
diff --git a/aconvert2/src/GasTexConverter.cpp b/aconvert2/src/GasTexConverter.cpp
index 984c01593a..1866ee7665 100644
--- a/aconvert2/src/GasTexConverter.cpp
+++ b/aconvert2/src/GasTexConverter.cpp
@@ -284,11 +284,11 @@ void GasTexConverter::convert(std::ostream& out, const automaton::CompactNFA < >
 
 auto GasTexConverterCompactNFA = GasTexConverter::RegistratorWrapper<void, automaton::CompactNFA < > >(GasTexConverter::convert);
 
-void GasTexConverter::convert(std::ostream&, const automaton::NFTA&) {
+void GasTexConverter::convert(std::ostream&, const automaton::NFTA < > &) {
 	//TODO
 }
 
-auto GasTexConverterNFTA = GasTexConverter::RegistratorWrapper<void, automaton::NFTA>(GasTexConverter::convert);
+auto GasTexConverterNFTA = GasTexConverter::RegistratorWrapper<void, automaton::NFTA < > >(GasTexConverter::convert);
 
 void GasTexConverter::convert(std::ostream&, const automaton::DFTA < > &) {
 	//TODO
@@ -907,7 +907,7 @@ void GasTexConverter::transitions(const automaton::CompactNFA < > & fsm, std::os
 	printTransitionMap(transitionMap, out);
 }
 
-void GasTexConverter::transitions(const automaton::NFTA&, std::ostream&) {
+void GasTexConverter::transitions(const automaton::NFTA < > &, std::ostream&) {
 	//TODO
 }
 
diff --git a/aconvert2/src/GasTexConverter.h b/aconvert2/src/GasTexConverter.h
index e7b6a5c2f5..41a455309d 100644
--- a/aconvert2/src/GasTexConverter.h
+++ b/aconvert2/src/GasTexConverter.h
@@ -27,7 +27,7 @@ class GasTexConverter : public std::SingleDispatchFirstStaticParam<GasTexConvert
 	static void transitions(const automaton::DFA<>& fsm, std::ostream& out);
 	static void transitions(const automaton::ExtendedNFA& fsm, std::ostream& out);
 	static void transitions(const automaton::CompactNFA < > & fsm, std::ostream& out);
-	static void transitions(const automaton::NFTA& fsm, std::ostream& out);
+	static void transitions(const automaton::NFTA < > & fsm, std::ostream& out);
 	static void transitions(const automaton::DFTA < > & fsm, std::ostream& out);
 	static void transitions(const automaton::DPDA < > & pda, std::ostream& out);
 	static void transitions(const automaton::SinglePopDPDA < > & tm, std::ostream& out);
@@ -49,7 +49,7 @@ public:
 	static void convert(std::ostream& out, const automaton::DFA<>& a);
 	static void convert(std::ostream& out, const automaton::ExtendedNFA& a);
 	static void convert(std::ostream& out, const automaton::CompactNFA < > & a);
-	static void convert(std::ostream& out, const automaton::NFTA& a);
+	static void convert(std::ostream& out, const automaton::NFTA < > & a);
 	static void convert(std::ostream& out, const automaton::DFTA < > & a);
 	static void convert(std::ostream& out, const automaton::DPDA < > & a);
 	static void convert(std::ostream& out, const automaton::SinglePopDPDA < > & a);
diff --git a/aconvert2/src/TikZConverter.cpp b/aconvert2/src/TikZConverter.cpp
index b84feb154c..4b072e5633 100644
--- a/aconvert2/src/TikZConverter.cpp
+++ b/aconvert2/src/TikZConverter.cpp
@@ -225,7 +225,7 @@ void TikZConverter::convert ( std::ostream & out, const automaton::CompactNFA <
 
 auto TikZConverterCompactNFA = TikZConverter::RegistratorWrapper < void, automaton::CompactNFA < > > ( TikZConverter::convert );
 
-void TikZConverter::convert ( std::ostream & out, const automaton::NFTA & a ) {
+void TikZConverter::convert ( std::ostream & out, const automaton::NFTA < > & a ) {
 	out << "\\begin{tikzpicture}\n";
 	int cnt = 1;
 
@@ -249,7 +249,7 @@ void TikZConverter::convert ( std::ostream & out, const automaton::NFTA & a ) {
 	out << "\\end{tikzpicture}";
 }
 
-auto TikZConverterNFTA = TikZConverter::RegistratorWrapper < void, automaton::NFTA > ( TikZConverter::convert );
+auto TikZConverterNFTA = TikZConverter::RegistratorWrapper < void, automaton::NFTA < > > ( TikZConverter::convert );
 
 void TikZConverter::convert ( std::ostream & out, const automaton::DFTA < > & a ) {
 	out << "\\begin{tikzpicture}\n";
@@ -851,7 +851,7 @@ void TikZConverter::transitions ( const automaton::CompactNFA < > & fsm, const s
 	}
 }
 
-void TikZConverter::transitions ( const automaton::NFTA & fta, const std::map < label::Label, int > & states, std::ostream & out ) {
+void TikZConverter::transitions ( const automaton::NFTA < > & fta, const std::map < label::Label, int > & states, std::ostream & out ) {
 	std::map < std::pair < int, std::vector < int > >, std::string > transitions;
 
 	 // put transitions from automaton to "transitions"
diff --git a/aconvert2/src/TikZConverter.h b/aconvert2/src/TikZConverter.h
index c7af7992f5..6507240a06 100644
--- a/aconvert2/src/TikZConverter.h
+++ b/aconvert2/src/TikZConverter.h
@@ -26,7 +26,7 @@ class TikZConverter : public std::SingleDispatchFirstStaticParam < TikZConverter
 	static void transitions ( const automaton::DFA<> & fsm, const std::map < label::Label, int > & states, std::ostream & out );
 	static void transitions ( const automaton::ExtendedNFA & fsm, const std::map < label::Label, int > & states, std::ostream & out );
 	static void transitions ( const automaton::CompactNFA < > & fsm, const std::map < label::Label, int > & states, std::ostream & out );
-	static void transitions ( const automaton::NFTA & fsm, const std::map < label::Label, int > & states, std::ostream & out );
+	static void transitions ( const automaton::NFTA < > & fsm, const std::map < label::Label, int > & states, std::ostream & out );
 	static void transitions ( const automaton::DFTA < > & fsm, const std::map < label::Label, int > & states, std::ostream & out );
 	static void transitions ( const automaton::DPDA < > & pda, const std::map < label::Label, int > & states, std::ostream & out );
 	static void transitions ( const automaton::SinglePopDPDA < > & tm, const std::map < label::Label, int > & states, std::ostream & out );
@@ -49,7 +49,7 @@ public:
 	static void convert ( std::ostream & out, const automaton::DFA<> & a );
 	static void convert ( std::ostream & out, const automaton::ExtendedNFA & a );
 	static void convert ( std::ostream & out, const automaton::CompactNFA < > & a );
-	static void convert ( std::ostream & out, const automaton::NFTA & a );
+	static void convert ( std::ostream & out, const automaton::NFTA < > & a );
 	static void convert ( std::ostream & out, const automaton::DFTA < > & a );
 	static void convert ( std::ostream & out, const automaton::DPDA < > & a );
 	static void convert ( std::ostream & out, const automaton::SinglePopDPDA < > & a );
diff --git a/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.cpp b/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.cpp
index f5ecd771fa..2a8e3f767f 100644
--- a/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.cpp
+++ b/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.cpp
@@ -189,13 +189,13 @@ automaton::VisiblyPushdownNPDA < > ExactPatternMatchingAutomaton::construct ( co
 
 auto ExactPatternMatchingAutomatonPrefixRankedBarPattern = ExactPatternMatchingAutomaton::RegistratorWrapper < automaton::VisiblyPushdownNPDA < >, tree::PrefixRankedBarPattern < > > ( ExactPatternMatchingAutomaton::construct );
 
-automaton::NFTA ExactPatternMatchingAutomaton::construct ( const tree::RankedTree < > & pattern ) {
+automaton::NFTA < > ExactPatternMatchingAutomaton::construct ( const tree::RankedTree < > & pattern ) {
 	return ExactSubtreeMatchingAutomaton::construct ( pattern );
 }
 
-auto ExactPatternMatchingAutomatonRankedTree = ExactPatternMatchingAutomaton::RegistratorWrapper < automaton::NFTA, tree::RankedTree < > > ( ExactPatternMatchingAutomaton::construct );
+auto ExactPatternMatchingAutomatonRankedTree = ExactPatternMatchingAutomaton::RegistratorWrapper < automaton::NFTA < >, tree::RankedTree < > > ( ExactPatternMatchingAutomaton::construct );
 
-label::Label constructRecursivePattern ( const std::tree < std::ranked_symbol < > > & node, automaton::NFTA & res, const std::ranked_symbol < > & subtreeWildcard, const label::Label & loopState, int & nextState ) {
+label::Label constructRecursivePattern ( const std::tree < std::ranked_symbol < > > & node, automaton::NFTA < > & res, const std::ranked_symbol < > & subtreeWildcard, const label::Label & loopState, int & nextState ) {
 	if ( node.getData ( ) == subtreeWildcard ) {
 		label::Label state = label::labelFrom ( nextState++ );
 		res.addState ( state );
@@ -225,12 +225,12 @@ label::Label constructRecursivePattern ( const std::tree < std::ranked_symbol <
 	}
 }
 
-automaton::NFTA ExactPatternMatchingAutomaton::construct ( const tree::RankedPattern < > & pattern ) {
+automaton::NFTA < > ExactPatternMatchingAutomaton::construct ( const tree::RankedPattern < > & pattern ) {
 	std::set < std::ranked_symbol < > > alphabet = pattern.getAlphabet ( );
 
 	alphabet.erase ( pattern.getSubtreeWildcard ( ) );
 
-	automaton::NFTA res;
+	automaton::NFTA < > res;
 	res.setInputAlphabet ( alphabet );
 
 	int nextState = 0;
@@ -252,7 +252,7 @@ automaton::NFTA ExactPatternMatchingAutomaton::construct ( const tree::RankedPat
 	return res;
 }
 
-auto ExactPatternMatchingAutomatonRankedPattern = ExactPatternMatchingAutomaton::RegistratorWrapper < automaton::NFTA, tree::RankedPattern < > > ( ExactPatternMatchingAutomaton::construct );
+auto ExactPatternMatchingAutomatonRankedPattern = ExactPatternMatchingAutomaton::RegistratorWrapper < automaton::NFTA < >, tree::RankedPattern < > > ( ExactPatternMatchingAutomaton::construct );
 
 } /* namespace exact */
 
diff --git a/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.h b/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.h
index 0c9c24ef82..df72f1086c 100644
--- a/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.h
+++ b/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.h
@@ -29,8 +29,8 @@ public:
 	static automaton::InputDrivenNPDA < > construct ( const tree::PrefixRankedTree < > & pattern );
 	static automaton::VisiblyPushdownNPDA < > construct ( const tree::PrefixRankedBarPattern < > & pattern );
 	static automaton::InputDrivenNPDA < > construct ( const tree::PrefixRankedBarTree < > & pattern );
-	static automaton::NFTA construct ( const tree::RankedTree < > & pattern );
-	static automaton::NFTA construct ( const tree::RankedPattern < > & pattern );
+	static automaton::NFTA < > construct ( const tree::RankedTree < > & pattern );
+	static automaton::NFTA < > construct ( const tree::RankedPattern < > & pattern );
 
 };
 
diff --git a/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.cpp b/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.cpp
index 6450d106e8..18d04e7fae 100644
--- a/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.cpp
+++ b/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.cpp
@@ -83,7 +83,7 @@ automaton::InputDrivenNPDA < > ExactSubtreeMatchingAutomaton::construct ( const
 
 auto ExactSubtreeMatchingAutomatonPrefixRankedBarTree = ExactSubtreeMatchingAutomaton::RegistratorWrapper < automaton::InputDrivenNPDA < >, tree::PrefixRankedBarTree < > > ( ExactSubtreeMatchingAutomaton::construct );
 
-label::Label constructRecursive ( const std::tree < std::ranked_symbol < > > & node, automaton::NFTA & res, int & nextState ) {
+label::Label constructRecursive ( const std::tree < std::ranked_symbol < > > & node, automaton::NFTA < > & res, int & nextState ) {
 	std::vector < label::Label > states;
 
 	states.reserve ( node.getData ( ).getRank ( ).getData ( ) );
@@ -97,8 +97,8 @@ label::Label constructRecursive ( const std::tree < std::ranked_symbol < > > & n
 	return state;
 }
 
-automaton::NFTA ExactSubtreeMatchingAutomaton::construct ( const tree::RankedTree < > & pattern ) {
-	automaton::NFTA res;
+automaton::NFTA < > ExactSubtreeMatchingAutomaton::construct ( const tree::RankedTree < > & pattern ) {
+	automaton::NFTA < > res;
 
 	res.setInputAlphabet ( pattern.getAlphabet ( ) );
 	int nextState = 0;
@@ -106,7 +106,7 @@ automaton::NFTA ExactSubtreeMatchingAutomaton::construct ( const tree::RankedTre
 	return res;
 }
 
-auto ExactSubtreeMatchingAutomatonRankedTree = ExactSubtreeMatchingAutomaton::RegistratorWrapper < automaton::NFTA, tree::RankedTree < > > ( ExactSubtreeMatchingAutomaton::construct );
+auto ExactSubtreeMatchingAutomatonRankedTree = ExactSubtreeMatchingAutomaton::RegistratorWrapper < automaton::NFTA < >, tree::RankedTree < > > ( ExactSubtreeMatchingAutomaton::construct );
 
 } /* namespace exact */
 
diff --git a/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.h b/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.h
index bf2bc215e1..8bef8361cb 100644
--- a/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.h
+++ b/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.h
@@ -28,7 +28,7 @@ public:
 
 	static automaton::InputDrivenNPDA < > construct ( const tree::PrefixRankedTree < > & pattern );
 	static automaton::InputDrivenNPDA < > construct ( const tree::PrefixRankedBarTree < > & pattern );
-	static automaton::NFTA construct ( const tree::RankedTree < > & pattern );
+	static automaton::NFTA < > construct ( const tree::RankedTree < > & pattern );
 
 };
 
diff --git a/alib2algo/src/automaton/determinize/Determinize.h b/alib2algo/src/automaton/determinize/Determinize.h
index 1c965d883c..9d7b245e5c 100644
--- a/alib2algo/src/automaton/determinize/Determinize.h
+++ b/alib2algo/src/automaton/determinize/Determinize.h
@@ -44,7 +44,7 @@ public:
 	static automaton::RealTimeHeightDeterministicDPDA < > determinize(const automaton::RealTimeHeightDeterministicDPDA < > & nondeterministic);
 	static automaton::RealTimeHeightDeterministicDPDA < > determinize(const automaton::RealTimeHeightDeterministicNPDA < > & nondeterministic);
 	static automaton::DFTA < > determinize(const automaton::DFTA < > & nfta);
-	static automaton::DFTA < > determinize(const automaton::NFTA& nfta);
+	static automaton::DFTA < > determinize(const automaton::NFTA < > & nfta);
 
 	static automaton::OneTapeDTM<> determinize(const automaton::OneTapeDTM<>& nfta);
 };
diff --git a/alib2algo/src/automaton/determinize/DeterminizeNFTAPart.cxx b/alib2algo/src/automaton/determinize/DeterminizeNFTAPart.cxx
index 9c01466106..75e8f915d0 100644
--- a/alib2algo/src/automaton/determinize/DeterminizeNFTAPart.cxx
+++ b/alib2algo/src/automaton/determinize/DeterminizeNFTAPart.cxx
@@ -15,7 +15,7 @@ namespace automaton {
 
 namespace determinize {
 
-std::set<label::Label> getTransitionRightSide(const NFTA & nfta, const std::ranked_symbol < > & symbol, const std::vector<label::Label> & states) {
+std::set<label::Label> getTransitionRightSide(const NFTA < > & nfta, const std::ranked_symbol < > & symbol, const std::vector<label::Label> & states) {
 	std::set<label::Label> res;
 	for (const auto & transition : nfta.getTransitions()) {
 		if (transition.first.first != symbol) continue;
@@ -29,7 +29,7 @@ std::set<label::Label> getTransitionRightSide(const NFTA & nfta, const std::rank
 	return res;
 }
 
-DFTA < > Determinize::determinize(const NFTA & nfta) {
+DFTA < > Determinize::determinize(const NFTA < > & nfta) {
 	DFTA < > res;
 	res.setInputAlphabet(nfta.getInputAlphabet());
 	for (const auto & state : nfta.getStates()) res.addState(createDFAState({state}));
@@ -94,7 +94,7 @@ DFTA < > Determinize::determinize(const NFTA & nfta) {
 	return res;
 }
 
-auto DeterminizeNFTA = Determinize::RegistratorWrapper<automaton::DFTA < >, automaton::NFTA>( Determinize::determinize );
+auto DeterminizeNFTA = Determinize::RegistratorWrapper<automaton::DFTA < >, automaton::NFTA < > >( Determinize::determinize );
 
 } /* namespace determinize */
 
diff --git a/alib2algo/src/automaton/run/Accept.cpp b/alib2algo/src/automaton/run/Accept.cpp
index 66542ffede..b6b6d4cf93 100644
--- a/alib2algo/src/automaton/run/Accept.cpp
+++ b/alib2algo/src/automaton/run/Accept.cpp
@@ -63,7 +63,7 @@ bool Accept::accept ( const automaton::DFTA < > & automaton, const tree::RankedT
 
 auto AcceptDFTARankedTree = Accept::RegistratorWrapper < bool, automaton::DFTA < >, tree::RankedTree < > > ( Accept::accept );
 
-bool Accept::accept ( const automaton::NFTA & automaton, const tree::RankedTree < > & tree ) {
+bool Accept::accept ( const automaton::NFTA < > & automaton, const tree::RankedTree < > & tree ) {
 	std::tuple < bool, std::set < label::Label >, std::set < unsigned > > res = Run::calculateStates ( automaton, tree );
 
 	return std::get < 0 > ( res ) && std::any_of ( std::get < 1 > ( res ).begin ( ), std::get < 1 > ( res ).end ( ), [&] ( const label::Label & state ) {
@@ -71,7 +71,7 @@ bool Accept::accept ( const automaton::NFTA & automaton, const tree::RankedTree
 			} );
 }
 
-auto AcceptNFTARankedTree = Accept::RegistratorWrapper < bool, automaton::NFTA, tree::RankedTree < > > ( Accept::accept );
+auto AcceptNFTARankedTree = Accept::RegistratorWrapper < bool, automaton::NFTA < >, tree::RankedTree < > > ( Accept::accept );
 
 bool Accept::accept ( const automaton::InputDrivenDPDA < > & automaton, const string::LinearString < > & string ) {
 	std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > res = Run::calculateState ( automaton, string );
diff --git a/alib2algo/src/automaton/run/Accept.h b/alib2algo/src/automaton/run/Accept.h
index 0bfd062abc..4da0f7044d 100644
--- a/alib2algo/src/automaton/run/Accept.h
+++ b/alib2algo/src/automaton/run/Accept.h
@@ -32,7 +32,7 @@ public:
 	static bool accept ( const automaton::DFA<> & automaton, const string::LinearString < > & string );
 	static bool accept ( const automaton::NFA < > & automaton, const string::LinearString < > & string );
 	static bool accept ( const automaton::DFTA < > & automaton, const tree::RankedTree < > & tree );
-	static bool accept ( const automaton::NFTA & automaton, const tree::RankedTree < > & tree );
+	static bool accept ( const automaton::NFTA < > & automaton, const tree::RankedTree < > & tree );
 	static bool accept ( const automaton::InputDrivenDPDA < > & automaton, const string::LinearString < > & string );
 	static bool accept ( const automaton::VisiblyPushdownDPDA < > & automaton, const string::LinearString < > & string );
 	static bool accept ( const automaton::RealTimeHeightDeterministicDPDA < > & automaton, const string::LinearString < > & string );
diff --git a/alib2algo/src/automaton/run/Run.cpp b/alib2algo/src/automaton/run/Run.cpp
index 8324dc0f5b..a42c83cc46 100644
--- a/alib2algo/src/automaton/run/Run.cpp
+++ b/alib2algo/src/automaton/run/Run.cpp
@@ -151,7 +151,7 @@ std::tuple < bool, label::Label, std::set < unsigned > > Run::calculateState ( c
 
 // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
-std::pair < bool, std::set < label::Label > > Run::calculateStates ( const automaton::NFTA & automaton, const std::tree < std::ranked_symbol < > > & node, std::set < unsigned > & occ, unsigned & i ) {
+std::pair < bool, std::set < label::Label > > Run::calculateStates ( const automaton::NFTA < > & automaton, const std::tree < std::ranked_symbol < > > & node, std::set < unsigned > & occ, unsigned & i ) {
 	std::vector < std::set < label::Label > > resStates;
 
 	resStates.reserve ( node.getData ( ).getRank ( ).getData ( ) );
@@ -192,7 +192,7 @@ std::pair < bool, std::set < label::Label > > Run::calculateStates ( const autom
 	return std::make_pair ( sign, states );
 }
 
-std::tuple < bool, std::set < label::Label >, std::set < unsigned > > Run::calculateStates ( const automaton::NFTA & automaton, const tree::RankedTree < > & tree ) {
+std::tuple < bool, std::set < label::Label >, std::set < unsigned > > Run::calculateStates ( const automaton::NFTA < > & automaton, const tree::RankedTree < > & tree ) {
 	std::set < unsigned > occ;
 	unsigned i = 0;
 	std::pair < bool, std::set < label::Label > > res = calculateStates ( automaton, tree.getContent ( ), occ, i );
diff --git a/alib2algo/src/automaton/run/Run.h b/alib2algo/src/automaton/run/Run.h
index 733bd5f990..82ec3157a0 100644
--- a/alib2algo/src/automaton/run/Run.h
+++ b/alib2algo/src/automaton/run/Run.h
@@ -21,14 +21,14 @@ namespace run {
 
 class Run {
 	static std::pair < bool, label::Label > calculateState ( const automaton::DFTA < > & automaton, const std::tree < std::ranked_symbol < > > & node, std::set < unsigned > & occ, unsigned & i );
-	static std::pair < bool, std::set < label::Label > > calculateStates ( const automaton::NFTA & automaton, const std::tree < std::ranked_symbol < > > & node, std::set < unsigned > & occ, unsigned & i );
+	static std::pair < bool, std::set < label::Label > > calculateStates ( const automaton::NFTA < > & automaton, const std::tree < std::ranked_symbol < > > & node, std::set < unsigned > & occ, unsigned & i );
 	static bool canPop ( const std::deque < alphabet::Symbol > & pushdownStore, const std::vector < alphabet::Symbol > & pop );
 
 public:
 	static std::tuple < bool, label::Label, std::set < unsigned > > calculateState ( const automaton::DFA < > & automaton, const string::LinearString < > & string );
 	static std::tuple < bool, std::set < label::Label >, std::set < unsigned > > calculateStates ( const automaton::NFA < > & automaton, const string::LinearString < > & string );
 	static std::tuple < bool, label::Label, std::set < unsigned > > calculateState ( const automaton::DFTA < > & automaton, const tree::RankedTree < > & tree );
-	static std::tuple < bool, std::set < label::Label >, std::set < unsigned > > calculateStates ( const automaton::NFTA & automaton, const tree::RankedTree < > & tree );
+	static std::tuple < bool, std::set < label::Label >, std::set < unsigned > > calculateStates ( const automaton::NFTA < > & automaton, const tree::RankedTree < > & tree );
 	static std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > calculateState ( const automaton::InputDrivenDPDA < > & automaton, const string::LinearString < > & string );
 	static std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > calculateState ( const automaton::VisiblyPushdownDPDA < > & automaton, const string::LinearString < > & string );
 	static std::tuple < bool, label::Label, std::set < unsigned >, std::deque < alphabet::Symbol > > calculateState ( const automaton::RealTimeHeightDeterministicDPDA < > & automaton, const string::LinearString < > & string );
diff --git a/alib2algo/test-src/automaton/determinize/determinizeTest.cpp b/alib2algo/test-src/automaton/determinize/determinizeTest.cpp
index d287a5ac15..bf4eb97d6d 100644
--- a/alib2algo/test-src/automaton/determinize/determinizeTest.cpp
+++ b/alib2algo/test-src/automaton/determinize/determinizeTest.cpp
@@ -108,7 +108,7 @@ void determinizeTest::testDeterminizeVPA() {
 }
 
 void determinizeTest::testDeterminizeNFTA() {
-  automaton::NFTA automaton;
+  automaton::NFTA < > automaton;
 
   const std::ranked_symbol < > a ('a', 2);
   const std::ranked_symbol < > b ('b', 1);
diff --git a/alib2data/src/automaton/AutomatonFeatures.h b/alib2data/src/automaton/AutomatonFeatures.h
index 78ac7c9093..a12f3729fd 100644
--- a/alib2data/src/automaton/AutomatonFeatures.h
+++ b/alib2data/src/automaton/AutomatonFeatures.h
@@ -78,6 +78,7 @@ template<class SymbolType = typename alphabet::Symbol, class StateType = typenam
 class OneTapeDTM;
 template<class SymbolType = typename alphabet::Symbol, class RankType = primitive::Unsigned, class StateType = typename label::Label >
 class DFTA;
+template<class SymbolType = typename alphabet::Symbol, class RankType = primitive::Unsigned, class StateType = typename label::Label >
 class NFTA;
 
 } /* namespace automaton */
diff --git a/alib2data/src/automaton/TA/NFTA.cpp b/alib2data/src/automaton/TA/NFTA.cpp
index 77f0881fc3..813cb3491c 100644
--- a/alib2data/src/automaton/TA/NFTA.cpp
+++ b/alib2data/src/automaton/TA/NFTA.cpp
@@ -6,163 +6,13 @@
  */
 
 #include "NFTA.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 <core/xmlApi.hpp>
 
-namespace automaton {
-
-NFTA::NFTA ( std::set < label::Label > states, std::set < std::ranked_symbol < > > inputAlphabet, std::set < label::Label > finalStates ) : std::Components < NFTA, std::ranked_symbol < >, std::tuple < InputAlphabet >, std::tuple < >, label::Label, std::tuple < States, FinalStates >, std::tuple < > > ( std::make_tuple ( std::move ( inputAlphabet ) ), std::tuple < > ( ), std::make_tuple ( std::move ( states ), std::move ( finalStates ) ), std::tuple < > ( ) ) {
-}
-
-NFTA::NFTA() : NFTA ( std::set < label::Label > { }, std::set < std::ranked_symbol < > > { }, std::set < label::Label > { } ) {
-}
-
-NFTA::NFTA(const DFTA < > & other) : NFTA ( other.getStates(), other.getInputAlphabet(), other.getFinalStates() ) {
-	for(const auto& transition : other.getTransitions()) {
-		transitions[transition.first].insert(transition.second);
-	}
-}
-
-AutomatonBase* NFTA::clone() const {
-	return new NFTA(*this);
-}
-
-AutomatonBase* NFTA::plunder() && {
-	return new NFTA(std::move(*this));
-}
-
-bool NFTA::addTransition(const std::ranked_symbol < > & symbol, const std::vector<label::Label> & prevStates, const label::Label & next) {
-	if (prevStates.size() != symbol.getRank().getData())
-		throw AutomatonException("Number of states doesn't match rank of the symbol");
-
-	if (! getInputAlphabet().count(symbol))
-		throw AutomatonException("Input symbol \"" + std::to_string ( symbol ) + "\" doesn't exist.");
-
-	if (! getStates().count(next))
-		throw AutomatonException("State \"" + std::to_string ( next ) + "\" doesn't exist.");
-
-	for (const label::Label& it : prevStates) {
-		if (! getStates().count(it))
-			throw AutomatonException("State \"" + std::to_string ( it ) + "\" doesn't exist.");
-	}
-
-	std::pair<std::ranked_symbol < >, std::vector<label::Label> > key = std::make_pair(symbol, prevStates);
-	return transitions[key].insert(next).second;
-}
-
-bool NFTA::removeTransition(const std::ranked_symbol < > symbol, const std::vector<label::Label> & states, const label::Label & next) {
-	std::pair<std::ranked_symbol < >, std::vector<label::Label> > key = std::make_pair(symbol, states);
-	return transitions[key].erase(next);
-}
-
-bool NFTA::isDeterministic() const {
-	for (const std::pair<const std::pair<std::ranked_symbol < >, std::vector<label::Label> >, std::set<label::Label> >& t : transitions)
-		if (t . second.size() != 1 || t . second.size() != 0)
-			return false;
-
-	return true;
-}
-
-unsigned NFTA::transitionsSize() const {
-	int res = 0;
-
-	for(const auto& transition : transitions )
-		res += transition.second.size();
-
-	return res;
-}
-
-int NFTA::compare(const NFTA& other) const {
-	auto first = std::tie(getStates(), getInputAlphabet(), getFinalStates(), transitions);
-	auto second = std::tie(other.getStates(), other.getInputAlphabet(), other.getFinalStates(), other.transitions);
-
-	std::compare<decltype(first)> comp;
-	return comp(first, second);
-}
-
-void NFTA::operator>>(std::ostream& out) const {
-	out << "(NFTA "
-		<< " states = " << getStates()
-		<< " inputAlphabet = " << getInputAlphabet()
-		<< " finalStates = " << getFinalStates()
-		<< " transitions = " << transitions
-		<< ")";
-}
-
-NFTA::operator std::string () const {
-	std::stringstream ss;
-	ss << *this;
-	return ss.str();
-}
-
-NFTA NFTA::parse(std::deque<sax::Token>::iterator& input) {
-	sax::FromXMLParserHelper::popToken(input, sax::Token::TokenType::START_ELEMENT, NFTA::getXmlTagName());
-
-	std::set<label::Label> states = AutomatonFromXMLParser::parseStates<label::Label>(input);
-	std::set<std::ranked_symbol < >> inputSymbols = AutomatonFromXMLParser::parseRankedInputAlphabet<std::ranked_symbol < >>(input);
-	std::set<label::Label> finalStates = AutomatonFromXMLParser::parseFinalStates<label::Label>(input);
-
-	NFTA automaton;
-	automaton.setStates(std::move(states));
-	automaton.setInputAlphabet(std::move(inputSymbols));
-	automaton.setFinalStates(std::move(finalStates));
-
-	AutomatonFromXMLParser::parseTransitions<NFTA>(input, automaton);
-
-	sax::FromXMLParserHelper::popToken(input, sax::Token::TokenType::END_ELEMENT, NFTA::getXmlTagName());
-	return automaton;
-}
-
-void NFTA::parseTransition(std::deque<sax::Token>::iterator& input, NFTA& automaton) {
-	sax::FromXMLParserHelper::popToken(input, sax::Token::TokenType::START_ELEMENT, "transition");
-	std::ranked_symbol < > inputSymbol = AutomatonFromXMLParser::parseTransitionInputSymbol<std::ranked_symbol < >>(input);
-	std::vector<label::Label> from = AutomatonFromXMLParser::parseTransitionFromMultiple<label::Label>(input);
-	label::Label to = AutomatonFromXMLParser::parseTransitionTo<label::Label>(input);
-	sax::FromXMLParserHelper::popToken(input, sax::Token::TokenType::END_ELEMENT, "transition");
-
-	automaton.addTransition(std::move(inputSymbol), std::move(from), std::move(to));
-}
-
-void NFTA::compose(std::deque<sax::Token>& out) const {
-	out.emplace_back(NFTA::getXmlTagName(), sax::Token::TokenType::START_ELEMENT);
-
-	AutomatonToXMLComposer::composeStates(out, this->getStates());
-	AutomatonToXMLComposer::composeRankedInputAlphabet(out, this->getInputAlphabet());
-	AutomatonToXMLComposer::composeFinalStates(out, this->getFinalStates());
-	composeTransitions(out);
-
-	out.emplace_back(NFTA::getXmlTagName(), sax::Token::TokenType::END_ELEMENT);
-}
-
-void NFTA::composeTransitions(std::deque<sax::Token>& out) const {
-	out.emplace_back(sax::Token("transitions", sax::Token::TokenType::START_ELEMENT));
-	for(const auto& transition : this->getTransitions()) {
-		for(const auto& targetState: transition.second) {
-			out.emplace_back(sax::Token("transition", sax::Token::TokenType::START_ELEMENT));
-
-			AutomatonToXMLComposer::composeTransitionInputSymbol(out, transition.first.first);
-			AutomatonToXMLComposer::composeTransitionFrom(out, transition.first.second);
-			AutomatonToXMLComposer::composeTransitionTo(out, targetState);
-
-			out.emplace_back(sax::Token("transition", sax::Token::TokenType::END_ELEMENT));
-		}
-	}
-
-	out.emplace_back(sax::Token("transitions", sax::Token::TokenType::END_ELEMENT));
-}
-
-} /* namespace automaton */
-
 namespace alib {
 
-auto NFTAParserRegister = xmlApi<automaton::Automaton>::ParserRegister<automaton::NFTA>();
-auto NFTAParserRegister2 = xmlApi<alib::Object>::ParserRegister<automaton::NFTA>();
+auto NFTAParserRegister = xmlApi < automaton::Automaton >::ParserRegister < automaton::NFTA < > > ( );
+auto NFTAParserRegister2 = xmlApi < alib::Object >::ParserRegister < automaton::NFTA < > > ( );
 
 } /* namespace alib */
diff --git a/alib2data/src/automaton/TA/NFTA.h b/alib2data/src/automaton/TA/NFTA.h
index ec34d49bc8..d7ec2fe37f 100644
--- a/alib2data/src/automaton/TA/NFTA.h
+++ b/alib2data/src/automaton/TA/NFTA.h
@@ -8,15 +8,19 @@
 #ifndef NFTA_H_
 #define NFTA_H_
 
-#include "../AutomatonException.h"
 #include <map>
 #include <vector>
+#include <ostream>
+#include <sstream>
+
 #include <core/components.hpp>
-#include "../AutomatonBase.h"
-#include "../../alphabet/RankedSymbol.h"
-#include "../../label/Label.h"
+#include <sax/FromXMLParserHelper.h>
 
-#include "DFTA.h"
+#include "../AutomatonBase.h"
+#include "../AutomatonFeatures.h"
+#include "../AutomatonException.h"
+#include "../common/AutomatonFromXMLParser.h"
+#include "../common/AutomatonToXMLComposer.h"
 
 namespace automaton {
 
@@ -28,68 +32,69 @@ class FinalStates;
  * Represents Finite Tree Automaton.
  * Can store nondeterministic finite tree automaton without epsilon transitions.
  */
-class NFTA : public AutomatonBase, public std::Components < NFTA, std::ranked_symbol < >, std::tuple < InputAlphabet >, std::tuple < >, label::Label, std::tuple < States, FinalStates >, std::tuple < > > {
-	std::map < std::pair < std::ranked_symbol < >, std::vector < label::Label > >, std::set < label::Label > > transitions;
+template < class SymbolType, class RankType, class StateType >
+class NFTA : public AutomatonBase, public std::Components < NFTA < SymbolType, RankType, StateType >, std::ranked_symbol < SymbolType, RankType >, std::tuple < InputAlphabet >, std::tuple < >, StateType, std::tuple < States, FinalStates >, std::tuple < > > {
+	std::map < std::pair < std::ranked_symbol < SymbolType, RankType >, std::vector < StateType > >, std::set < StateType > > transitions;
 
 public:
 	explicit NFTA ( );
-	explicit NFTA ( std::set < label::Label > states, std::set < std::ranked_symbol < > > inputAlphabet, std::set < label::Label > finalStates );
+	explicit NFTA ( std::set < StateType > states, std::set < std::ranked_symbol < SymbolType, RankType > > inputAlphabet, std::set < StateType > finalStates );
 	explicit NFTA ( const DFTA < > & other );
 
 	virtual AutomatonBase * clone ( ) const;
 
 	virtual AutomatonBase * plunder ( ) &&;
 
-	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 < std::ranked_symbol < > > & getInputAlphabet ( ) const {
-		return accessComponent < InputAlphabet > ( ).get ( );
+	const std::set < std::ranked_symbol < SymbolType, RankType > > & getInputAlphabet ( ) const {
+		return this->template accessComponent < InputAlphabet > ( ).get ( );
 	}
 
-	bool addInputSymbol ( std::ranked_symbol < > symbol ) {
-		return accessComponent < InputAlphabet > ( ).add ( std::move ( symbol ) );
+	bool addInputSymbol ( std::ranked_symbol < SymbolType, RankType > symbol ) {
+		return this->template accessComponent < InputAlphabet > ( ).add ( std::move ( symbol ) );
 	}
 
-	void addInputSymbols ( std::set < std::ranked_symbol < > > symbols ) {
-		accessComponent < InputAlphabet > ( ).add ( std::move ( symbols ) );
+	void addInputSymbols ( std::set < std::ranked_symbol < SymbolType, RankType > > symbols ) {
+		this->template accessComponent < InputAlphabet > ( ).add ( std::move ( symbols ) );
 	}
 
-	void setInputAlphabet ( std::set < std::ranked_symbol < > > symbols ) {
-		accessComponent < InputAlphabet > ( ).set ( std::move ( symbols ) );
+	void setInputAlphabet ( std::set < std::ranked_symbol < SymbolType, RankType > > symbols ) {
+		this->template accessComponent < InputAlphabet > ( ).set ( std::move ( symbols ) );
 	}
 
-	void removeInputSymbol ( const std::ranked_symbol < > & symbol ) {
-		accessComponent < InputAlphabet > ( ).remove ( symbol );
+	void removeInputSymbol ( const std::ranked_symbol < SymbolType, RankType > & symbol ) {
+		this->template accessComponent < InputAlphabet > ( ).remove ( symbol );
 	}
 
 	/**
@@ -99,20 +104,20 @@ 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 ( const std::ranked_symbol < > & current, const std::vector < label::Label > & children, const label::Label & next );
+	bool addTransition ( const std::ranked_symbol < SymbolType, RankType > & current, const std::vector < StateType > & children, const StateType & next );
 
 	/**
 	 * Removes transition from the automaton.
 	 * @throws AutomatonException when transition doesn't exists.
 	 */
-	bool removeTransition ( const std::ranked_symbol < > symbol, const std::vector < label::Label > & states, const label::Label & next );
+	bool removeTransition ( const std::ranked_symbol < SymbolType, RankType > symbol, const std::vector < StateType > & states, const StateType & next );
 
 	/**
 	 * @return automaton transitions
 	 */
-	const std::map < std::pair < std::ranked_symbol < >, std::vector < label::Label > >, std::set < label::Label > > & getTransitions ( ) const { return transitions; }
+	const std::map < std::pair < std::ranked_symbol < SymbolType, RankType >, std::vector < StateType > >, std::set < StateType > > & getTransitions ( ) const { return transitions; }
 
-	std::set < label::Label > getTransitionRightSide ( const std::ranked_symbol < > symbol, const std::vector < label::Label > & states );
+	std::set < StateType > getTransitionRightSide ( const std::ranked_symbol < SymbolType, RankType > symbol, const std::vector < StateType > & states );
 
 	/**
 	 * Determines whether NFTA is deterministic.
@@ -152,61 +157,223 @@ public:
 
 } /* namespace automaton */
 
+#include "DFTA.h"
+
+namespace automaton {
+
+template < class SymbolType, class RankType, class StateType >
+NFTA < SymbolType, RankType, StateType >::NFTA ( std::set < StateType > states, std::set < std::ranked_symbol < SymbolType, RankType > > inputAlphabet, std::set < StateType > finalStates ) : std::Components < NFTA, std::ranked_symbol < SymbolType, RankType >, std::tuple < InputAlphabet >, std::tuple < >, StateType, std::tuple < States, FinalStates >, std::tuple < > > ( std::make_tuple ( std::move ( inputAlphabet ) ), std::tuple < > ( ), std::make_tuple ( std::move ( states ), std::move ( finalStates ) ), std::tuple < > ( ) ) {
+}
+
+template < class SymbolType, class RankType, class StateType >
+NFTA < SymbolType, RankType, StateType >::NFTA() : NFTA ( std::set < StateType > { }, std::set < std::ranked_symbol < SymbolType, RankType > > { }, std::set < StateType > { } ) {
+}
+
+template < class SymbolType, class RankType, class StateType >
+NFTA < SymbolType, RankType, StateType >::NFTA(const DFTA < > & other) : NFTA ( other.getStates(), other.getInputAlphabet(), other.getFinalStates() ) {
+	for(const auto& transition : other.getTransitions()) {
+		transitions[transition.first].insert(transition.second);
+	}
+}
+
+template < class SymbolType, class RankType, class StateType >
+AutomatonBase* NFTA < SymbolType, RankType, StateType >::clone() const {
+	return new NFTA(*this);
+}
+
+template < class SymbolType, class RankType, class StateType >
+AutomatonBase* NFTA < SymbolType, RankType, StateType >::plunder() && {
+	return new NFTA(std::move(*this));
+}
+
+template < class SymbolType, class RankType, class StateType >
+bool NFTA < SymbolType, RankType, StateType >::addTransition(const std::ranked_symbol < SymbolType, RankType > & symbol, const std::vector<StateType> & prevStates, const StateType & next) {
+	if (prevStates.size() != symbol.getRank().getData())
+		throw AutomatonException("Number of states doesn't match rank of the symbol");
+
+	if (! getInputAlphabet().count(symbol))
+		throw AutomatonException("Input symbol \"" + std::to_string ( symbol ) + "\" doesn't exist.");
+
+	if (! getStates().count(next))
+		throw AutomatonException("State \"" + std::to_string ( next ) + "\" doesn't exist.");
+
+	for (const StateType& it : prevStates) {
+		if (! getStates().count(it))
+			throw AutomatonException("State \"" + std::to_string ( it ) + "\" doesn't exist.");
+	}
+
+	std::pair<std::ranked_symbol < SymbolType, RankType >, std::vector<StateType> > key = std::make_pair(symbol, prevStates);
+	return transitions[key].insert(next).second;
+}
+
+template < class SymbolType, class RankType, class StateType >
+bool NFTA < SymbolType, RankType, StateType >::removeTransition(const std::ranked_symbol < SymbolType, RankType > symbol, const std::vector<StateType> & states, const StateType & next) {
+	std::pair<std::ranked_symbol < SymbolType, RankType >, std::vector<StateType> > key = std::make_pair(symbol, states);
+	return transitions[key].erase(next);
+}
+
+template < class SymbolType, class RankType, class StateType >
+bool NFTA < SymbolType, RankType, StateType >::isDeterministic() const {
+	for (const std::pair<const std::pair<std::ranked_symbol < SymbolType, RankType >, std::vector<StateType> >, std::set<StateType> >& t : transitions)
+		if (t . second.size() != 1 || t . second.size() != 0)
+			return false;
+
+	return true;
+}
+
+template < class SymbolType, class RankType, class StateType >
+unsigned NFTA < SymbolType, RankType, StateType >::transitionsSize() const {
+	int res = 0;
+
+	for(const auto& transition : transitions )
+		res += transition.second.size();
+
+	return res;
+}
+
+template < class SymbolType, class RankType, class StateType >
+int NFTA < SymbolType, RankType, StateType >::compare(const NFTA& other) const {
+	auto first = std::tie(getStates(), getInputAlphabet(), getFinalStates(), transitions);
+	auto second = std::tie(other.getStates(), other.getInputAlphabet(), other.getFinalStates(), other.transitions);
+
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
+}
+
+template < class SymbolType, class RankType, class StateType >
+void NFTA < SymbolType, RankType, StateType >::operator>>(std::ostream& out) const {
+	out << "(NFTA "
+		<< " states = " << getStates()
+		<< " inputAlphabet = " << getInputAlphabet()
+		<< " finalStates = " << getFinalStates()
+		<< " transitions = " << transitions
+		<< ")";
+}
+
+template < class SymbolType, class RankType, class StateType >
+NFTA < SymbolType, RankType, StateType >::operator std::string () const {
+	std::stringstream ss;
+	ss << *this;
+	return ss.str();
+}
+
+template < class SymbolType, class RankType, class StateType >
+NFTA < SymbolType, RankType, StateType > NFTA < SymbolType, RankType, StateType >::parse(std::deque<sax::Token>::iterator& input) {
+	sax::FromXMLParserHelper::popToken(input, sax::Token::TokenType::START_ELEMENT, NFTA::getXmlTagName());
+
+	std::set<StateType> states = AutomatonFromXMLParser::parseStates<StateType>(input);
+	std::set<std::ranked_symbol < SymbolType, RankType >> inputSymbols = AutomatonFromXMLParser::parseRankedInputAlphabet<std::ranked_symbol < SymbolType, RankType >>(input);
+	std::set<StateType> finalStates = AutomatonFromXMLParser::parseFinalStates<StateType>(input);
+
+	NFTA < SymbolType, RankType, StateType > automaton;
+	automaton.setStates(std::move(states));
+	automaton.setInputAlphabet(std::move(inputSymbols));
+	automaton.setFinalStates(std::move(finalStates));
+
+	AutomatonFromXMLParser::parseTransitions<NFTA>(input, automaton);
+
+	sax::FromXMLParserHelper::popToken(input, sax::Token::TokenType::END_ELEMENT, NFTA::getXmlTagName());
+	return automaton;
+}
+
+template < class SymbolType, class RankType, class StateType >
+void NFTA < SymbolType, RankType, StateType >::parseTransition(std::deque<sax::Token>::iterator& input, NFTA& automaton) {
+	sax::FromXMLParserHelper::popToken(input, sax::Token::TokenType::START_ELEMENT, "transition");
+	std::ranked_symbol < SymbolType, RankType > inputSymbol = AutomatonFromXMLParser::parseTransitionInputSymbol<std::ranked_symbol < SymbolType, RankType >>(input);
+	std::vector<StateType> from = AutomatonFromXMLParser::parseTransitionFromMultiple<StateType>(input);
+	StateType to = AutomatonFromXMLParser::parseTransitionTo<StateType>(input);
+	sax::FromXMLParserHelper::popToken(input, sax::Token::TokenType::END_ELEMENT, "transition");
+
+	automaton.addTransition(std::move(inputSymbol), std::move(from), std::move(to));
+}
+
+template < class SymbolType, class RankType, class StateType >
+void NFTA < SymbolType, RankType, StateType >::compose(std::deque<sax::Token>& out) const {
+	out.emplace_back(NFTA::getXmlTagName(), sax::Token::TokenType::START_ELEMENT);
+
+	AutomatonToXMLComposer::composeStates(out, this->getStates());
+	AutomatonToXMLComposer::composeRankedInputAlphabet(out, this->getInputAlphabet());
+	AutomatonToXMLComposer::composeFinalStates(out, this->getFinalStates());
+	composeTransitions(out);
+
+	out.emplace_back(NFTA::getXmlTagName(), sax::Token::TokenType::END_ELEMENT);
+}
+
+template < class SymbolType, class RankType, class StateType >
+void NFTA < SymbolType, RankType, StateType >::composeTransitions(std::deque<sax::Token>& out) const {
+	out.emplace_back(sax::Token("transitions", sax::Token::TokenType::START_ELEMENT));
+	for(const auto& transition : this->getTransitions()) {
+		for(const auto& targetState: transition.second) {
+			out.emplace_back(sax::Token("transition", sax::Token::TokenType::START_ELEMENT));
+
+			AutomatonToXMLComposer::composeTransitionInputSymbol(out, transition.first.first);
+			AutomatonToXMLComposer::composeTransitionFrom(out, transition.first.second);
+			AutomatonToXMLComposer::composeTransitionTo(out, targetState);
+
+			out.emplace_back(sax::Token("transition", sax::Token::TokenType::END_ELEMENT));
+		}
+	}
+
+	out.emplace_back(sax::Token("transitions", sax::Token::TokenType::END_ELEMENT));
+}
+
+} /* namespace automaton */
+
 namespace std {
 
-template < >
-class ComponentConstraint< automaton::NFTA, std::ranked_symbol < >, automaton::InputAlphabet > {
+template < class SymbolType, class RankType, class StateType >
+class ComponentConstraint< automaton::NFTA < SymbolType, RankType, StateType >, std::ranked_symbol < SymbolType, RankType >, automaton::InputAlphabet > {
 public:
-	static bool used ( const automaton::NFTA & automaton, const std::ranked_symbol < > & symbol ) {
-		for (const std::pair<const std::pair<std::ranked_symbol < >, std::vector<label::Label> >, std::set<label::Label>>& t : automaton.getTransitions())
+	static bool used ( const automaton::NFTA < SymbolType, RankType, StateType > & automaton, const std::ranked_symbol < SymbolType, RankType > & symbol ) {
+		for (const std::pair<const std::pair<std::ranked_symbol < SymbolType, RankType >, std::vector<StateType> >, std::set<StateType>>& t : automaton.getTransitions())
 			if (t.first.first == symbol)
 				return true;
 
 		return false;
 	}
 
-	static bool available ( const automaton::NFTA &, const std::ranked_symbol < > & ) {
+	static bool available ( const automaton::NFTA < SymbolType, RankType, StateType > &, const std::ranked_symbol < SymbolType, RankType > & ) {
 		return true;
 	}
 
-	static void valid ( const automaton::NFTA &, const std::ranked_symbol < > & ) {
+	static void valid ( const automaton::NFTA < SymbolType, RankType, StateType > &, const std::ranked_symbol < SymbolType, RankType > & ) {
 	}
 };
 
-template < >
-class ComponentConstraint< automaton::NFTA, label::Label, automaton::States > {
+template < class SymbolType, class RankType, class StateType >
+class ComponentConstraint< automaton::NFTA < SymbolType, RankType, StateType >, StateType, automaton::States > {
 public:
-	static bool used ( const automaton::NFTA & automaton, const label::Label & state ) {
+	static bool used ( const automaton::NFTA < SymbolType, RankType, StateType > & automaton, const StateType & state ) {
 		if ( automaton.getFinalStates ( ).count ( state ) )
 			return true;
 
-		for (const std::pair<const std::pair<std::ranked_symbol < >, std::vector<label::Label> >, std::set<label::Label>>& t : automaton.getTransitions())
+		for (const std::pair<const std::pair<std::ranked_symbol < SymbolType, RankType >, std::vector<StateType> >, std::set<StateType>>& t : automaton.getTransitions())
 			if(std::contains(t.first.second.begin(), t.first.second.end(), state ) || t . second.count ( state ) )
 				return true;
 
 		return false;
 	}
 
-	static bool available ( const automaton::NFTA &, const label::Label & ) {
+	static bool available ( const automaton::NFTA < SymbolType, RankType, StateType > &, const StateType & ) {
 		return true;
 	}
 
-	static void valid ( const automaton::NFTA &, const label::Label & ) {
+	static void valid ( const automaton::NFTA < SymbolType, RankType, StateType > &, const StateType & ) {
 	}
 };
 
-template < >
-class ComponentConstraint< automaton::NFTA, label::Label, automaton::FinalStates > {
+template < class SymbolType, class RankType, class StateType >
+class ComponentConstraint< automaton::NFTA < SymbolType, RankType, StateType >, StateType, automaton::FinalStates > {
 public:
-	static bool used ( const automaton::NFTA &, const label::Label & ) {
+	static bool used ( const automaton::NFTA < SymbolType, RankType, StateType > &, const StateType & ) {
 		return false;
 	}
 
-	static bool available ( const automaton::NFTA & automaton, const label::Label & state ) {
-		return automaton.accessComponent < automaton::States > ( ).get ( ).count ( state );
+	static bool available ( const automaton::NFTA < SymbolType, RankType, StateType > & automaton, const StateType & state ) {
+		return automaton.template accessComponent < automaton::States > ( ).get ( ).count ( state );
 	}
 
-	static void valid ( const automaton::NFTA &, const label::Label & ) {
+	static void valid ( const automaton::NFTA < SymbolType, RankType, StateType > &, const StateType & ) {
 	}
 };
 
diff --git a/alib2data/test-src/automaton/AutomatonTest.cpp b/alib2data/test-src/automaton/AutomatonTest.cpp
index d210332a04..79d6abb596 100644
--- a/alib2data/test-src/automaton/AutomatonTest.cpp
+++ b/alib2data/test-src/automaton/AutomatonTest.cpp
@@ -243,7 +243,7 @@ void AutomatonTest::testNFTAParser() {
 	label::Label q1 = label::labelFrom ("q1");
 	label::Label q0 = label::labelFrom ("q0");
 
-	automaton::NFTA automaton;
+	automaton::NFTA < > automaton;
 
 	automaton.addState(q2);
 	automaton.addState(q1);
@@ -272,7 +272,7 @@ void AutomatonTest::testNFTAParser() {
 
 		std::deque<sax::Token> tokens2;
 		sax::SaxParseInterface::parseMemory(tmp, tokens2);
-		automaton::NFTA automaton2 = alib::XmlDataFactory::fromTokens<automaton::NFTA>(std::move(tokens2));
+		automaton::NFTA < > automaton2 = alib::XmlDataFactory::fromTokens<automaton::NFTA < > >(std::move(tokens2));
 
 		CPPUNIT_ASSERT( automaton == automaton2 );
 	}
@@ -288,7 +288,7 @@ void AutomatonTest::testNFTATransitions() {
 	label::Label q1 = label::labelFrom ("q1");
 	label::Label q0 = label::labelFrom ("q0");
 
-	automaton::NFTA automaton;
+	automaton::NFTA < > automaton;
 
 	automaton.addState(q2);
 	automaton.addState(q1);
-- 
GitLab