diff --git a/acompare2/src/AutomatonCompare.cpp b/acompare2/src/AutomatonCompare.cpp
index ebd81291374a2acc7698dc7648facc14ca8d0f50..3a685478dbb5ab3cac243290a6914bc8817c7f38 100644
--- a/acompare2/src/AutomatonCompare.cpp
+++ b/acompare2/src/AutomatonCompare.cpp
@@ -25,6 +25,8 @@
 #include "automaton/FSM/EpsilonNFA.h"
 #include "automaton/FSM/ExtendedNFA.h"
 #include "automaton/FSM/CompactNFA.h"
+#include "automaton/TA/DFTA.h"
+#include "automaton/TA/NFTA.h"
 #include "automaton/PDA/NPDA.h"
 #include "automaton/PDA/DPDA.h"
 #include "automaton/PDA/InputDrivenNPDA.h"
@@ -87,6 +89,20 @@ bool AutomatonCompare::testCompare(const automaton::CompactNFA& a, const automat
 			a.getTransitions()    == b.getTransitions()    ;
 }
 
+bool AutomatonCompare::testCompare(const automaton::DFTA& a, const automaton::DFTA& b) {
+	return  	a.getFinalStates()    == b.getFinalStates()    &&
+//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
+			a.getStates()         == b.getStates()         &&
+			a.getTransitions()    == b.getTransitions()    ;
+}
+
+bool AutomatonCompare::testCompare(const automaton::NFTA& a, const automaton::NFTA& b) {
+	return  	a.getFinalStates()    == b.getFinalStates()    &&
+//			a.getInputAlphabet()  == b.getInputAlphabet()  &&
+			a.getStates()         == b.getStates()         &&
+			a.getTransitions()    == b.getTransitions()    ;
+}
+
 bool AutomatonCompare::testCompare(const automaton::DPDA& a, const automaton::DPDA& b) {
 	return  	a.getFinalStates()    == b.getFinalStates()    &&
 			a.getInitialState()   == b.getInitialState()   &&
@@ -473,6 +489,62 @@ void AutomatonCompare::printCompare(const automaton::CompactNFA& a, const automa
 	}
 }
 
+void AutomatonCompare::printCompare(const automaton::DFTA& a, const automaton::DFTA& b) {
+	std::cout << "AutomatonCompareer" << std::endl;
+
+	if(a.getFinalStates() != b.getFinalStates()){
+		std::cout << "FinalStates" << std::endl;
+
+		AutomatonCompare::setCompare(a.getFinalStates(), b.getFinalStates());
+	}
+
+	if(a.getInputAlphabet() != b.getInputAlphabet()) {
+		std::cout << "InputAlphabet" << std::endl;
+
+		AutomatonCompare::setCompare(a.getInputAlphabet(), b.getInputAlphabet());
+	}
+
+	if(a.getStates() != b.getStates()) {
+		std::cout << "States" << std::endl;
+
+		AutomatonCompare::setCompare(a.getStates(), b.getStates());
+	}
+
+	if(a.getTransitions() != b.getTransitions()) {
+		std::cout << "Transitions" << std::endl;
+
+		AutomatonCompare::mapCompare(a.getTransitions(), b.getTransitions());
+	}
+}
+
+void AutomatonCompare::printCompare(const automaton::NFTA& a, const automaton::NFTA& b) {
+	std::cout << "AutomatonCompareer" << std::endl;
+
+	if(a.getFinalStates() != b.getFinalStates()){
+		std::cout << "FinalStates" << std::endl;
+
+		AutomatonCompare::setCompare(a.getFinalStates(), b.getFinalStates());
+	}
+
+	if(a.getInputAlphabet() != b.getInputAlphabet()) {
+		std::cout << "InputAlphabet" << std::endl;
+
+		AutomatonCompare::setCompare(a.getInputAlphabet(), b.getInputAlphabet());
+	}
+
+	if(a.getStates() != b.getStates()) {
+		std::cout << "States" << std::endl;
+
+		AutomatonCompare::setCompare(a.getStates(), b.getStates());
+	}
+
+	if(a.getTransitions() != b.getTransitions()) {
+		std::cout << "Transitions" << std::endl;
+
+		AutomatonCompare::mapCompare(a.getTransitions(), b.getTransitions());
+	}
+}
+
 void AutomatonCompare::printCompare(const automaton::DPDA& a, const automaton::DPDA& b) {
 	std::cout << "AutomatonCompareer" << std::endl;
 
@@ -1157,6 +1229,24 @@ int AutomatonCompare::compare(const automaton::CompactNFA& a, const automaton::C
 	}
 }
 
+int AutomatonCompare::compare(const automaton::DFTA& a, const automaton::DFTA& b) {
+	if(!AutomatonCompare::testCompare(a, b)) {
+	  AutomatonCompare::printCompare(a, b);
+	  return 1;
+	} else {
+	  return 0;
+	}
+}
+
+int AutomatonCompare::compare(const automaton::NFTA& a, const automaton::NFTA& b) {
+	if(!AutomatonCompare::testCompare(a, b)) {
+	  AutomatonCompare::printCompare(a, b);
+	  return 1;
+	} else {
+	  return 0;
+	}
+}
+
 int AutomatonCompare::compare(const automaton::DPDA& a, const automaton::DPDA& b) {
 	if(!AutomatonCompare::testCompare(a, b)) {
 	  AutomatonCompare::printCompare(a, b);
@@ -1286,6 +1376,14 @@ void AutomatonCompare::Visit(void* data, const automaton::NFA& first, const auto
 	*((int*) data) = AutomatonCompare::compare(first, second);
 }
 
+void AutomatonCompare::Visit(void* data, const automaton::DFTA& first, const automaton::DFTA& second) const {
+	*((int*) data) = AutomatonCompare::compare(first, second);
+}
+
+void AutomatonCompare::Visit(void* data, const automaton::NFTA& first, const automaton::NFTA& second) const {
+	*((int*) data) = AutomatonCompare::compare(first, second);
+}
+
 void AutomatonCompare::Visit(void* data, const automaton::DPDA& first, const automaton::DPDA& second) const {
 	*((int*) data) = AutomatonCompare::compare(first, second);
 }
diff --git a/acompare2/src/AutomatonCompare.h b/acompare2/src/AutomatonCompare.h
index ac97ae0513b88ee3fb5f077764179dcd4531ea1c..58bcc32835947c71854ec8df6a9ada0ebdf02e2e 100644
--- a/acompare2/src/AutomatonCompare.h
+++ b/acompare2/src/AutomatonCompare.h
@@ -41,6 +41,12 @@ class AutomatonCompare : public automaton::VisitableAutomatonBase::const_same_vi
 	static bool testCompare(const automaton::NPDA& a, const automaton::NPDA& b);
 	static void printCompare(const automaton::NPDA& a, const automaton::NPDA& b);
 
+	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::InputDrivenDPDA& a, const automaton::InputDrivenDPDA& b);
 	static void printCompare(const automaton::InputDrivenDPDA& a, const automaton::InputDrivenDPDA& b);
 
@@ -79,6 +85,9 @@ public:
 	void Visit(void* data, const automaton::MultiInitialStateNFA& first, const automaton::MultiInitialStateNFA& second) const;
 	void Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const;
 
+	void Visit(void* data, const automaton::DFTA& first, const automaton::DFTA& second) const;
+	void Visit(void* data, const automaton::NFTA& first, const automaton::NFTA& second) const;
+
 	void Visit(void* data, const automaton::DPDA& first, const automaton::DPDA& second) const;
 	void Visit(void* data, const automaton::NPDA& first, const automaton::NPDA& second) const;
 	void Visit(void* data, const automaton::InputDrivenNPDA& first, const automaton::InputDrivenNPDA& second) const;
@@ -99,6 +108,9 @@ public:
 	static int compare(const automaton::ExtendedNFA& a, const automaton::ExtendedNFA& b);
 	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::DPDA& a, const automaton::DPDA& b);
 	static int compare(const automaton::NPDA& a, const automaton::NPDA& b);
 	static int compare(const automaton::InputDrivenDPDA& a, const automaton::InputDrivenDPDA& b);
diff --git a/aconvert2/src/DotConverter.cpp b/aconvert2/src/DotConverter.cpp
index 3801066f966d7a1f97e4cfb6b1528eaa7860e3f0..ece17ebb619b40cd596c66188f864984a955b4b1 100644
--- a/aconvert2/src/DotConverter.cpp
+++ b/aconvert2/src/DotConverter.cpp
@@ -238,6 +238,14 @@ void DotConverter::convert(const automaton::CompactNFA& a, std::ostream& out) {
 	out << "}";
 }
 
+void DotConverter::convert(const automaton::NFTA&, std::ostream&) {
+	//TODO
+}
+
+void DotConverter::convert(const automaton::DFTA&, std::ostream&) {
+	//TODO
+}
+
 void DotConverter::convert(const automaton::DPDA& a, std::ostream& out) {
 	out << "digraph automaton {\n";
 	out << "rankdir=LR;\n";
@@ -790,6 +798,14 @@ void DotConverter::transitions(const automaton::CompactNFA& fsm, const std::map<
 	}
 }
 
+void DotConverter::transitions(const automaton::NFTA&, const std::map<automaton::State, int>&, std::ostream&) {
+	//TODO
+}
+
+void DotConverter::transitions(const automaton::DFTA&, const std::map<automaton::State, int>&, std::ostream&) {
+	//TODO
+}
+
 void DotConverter::transitions(const automaton::DPDA& pda, const std::map<automaton::State, int>& states, std::ostream& out) {
 	std::map<std::pair<int, int>, std::string> transitions;
 
@@ -1758,3 +1774,11 @@ void DotConverter::Visit(void* data, const automaton::OneTapeDTM& automaton) con
 	DotConverter::convert(automaton, *((std::ostream*) data));
 }
 
+void DotConverter::Visit(void* data, const automaton::NFTA& automaton) const {
+	DotConverter::convert(automaton, *((std::ostream*) data));
+}
+
+void DotConverter::Visit(void* data, const automaton::DFTA& automaton) const {
+	DotConverter::convert(automaton, *((std::ostream*) data));
+}
+
diff --git a/aconvert2/src/DotConverter.h b/aconvert2/src/DotConverter.h
index 5a9e26086da5e96ca5be50ad02b6f1d27d3a46ed..3e3d3c88e825a216da10a63f7b23dcdd89195648 100644
--- a/aconvert2/src/DotConverter.h
+++ b/aconvert2/src/DotConverter.h
@@ -33,6 +33,8 @@ class DotConverter : public automaton::VisitableAutomatonBase::const_visitor_typ
 	void Visit(void*, const automaton::NPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
 	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
 
 	static void transitions(const automaton::EpsilonNFA& fsm, const std::map<automaton::State, int>& states, std::ostream& out);
 	static void transitions(const automaton::MultiInitialStateNFA& fsm, const std::map<automaton::State, int>& states, std::ostream& out);
@@ -40,6 +42,8 @@ class DotConverter : public automaton::VisitableAutomatonBase::const_visitor_typ
 	static void transitions(const automaton::DFA& fsm, const std::map<automaton::State, int>& states, std::ostream& out);
 	static void transitions(const automaton::ExtendedNFA& fsm, const std::map<automaton::State, int>& states, std::ostream& out);
 	static void transitions(const automaton::CompactNFA& fsm, const std::map<automaton::State, int>& states, std::ostream& out);
+	static void transitions(const automaton::NFTA& fsm, const std::map<automaton::State, int>& states, std::ostream& out);
+	static void transitions(const automaton::DFTA& fsm, const std::map<automaton::State, int>& states, std::ostream& out);
 	static void transitions(const automaton::DPDA& pda, const std::map<automaton::State, int>& states, std::ostream& out);
 	static void transitions(const automaton::SinglePopDPDA& tm, const std::map<automaton::State, int>& states, std::ostream& out);
 	static void transitions(const automaton::InputDrivenDPDA& pda, const std::map<automaton::State, int>& states, std::ostream& out);
@@ -62,6 +66,8 @@ public:
 	static void convert(const automaton::DFA& a, std::ostream& out);
 	static void convert(const automaton::ExtendedNFA& a, std::ostream& out);
 	static void convert(const automaton::CompactNFA& a, std::ostream& out);
+	static void convert(const automaton::NFTA& a, std::ostream& out);
+	static void convert(const automaton::DFTA& a, std::ostream& out);
 	static void convert(const automaton::DPDA& a, std::ostream& out);
 	static void convert(const automaton::SinglePopDPDA& a, std::ostream& out);
 	static void convert(const automaton::InputDrivenDPDA& a, std::ostream& out);
diff --git a/aconvert2/src/GasTexConverter.cpp b/aconvert2/src/GasTexConverter.cpp
index d8635bcbe1700aa6559c76cbd97b4809fd82a6f2..f03a4a0a77e8f77df947bf0ca41c0ac5f559eac1 100644
--- a/aconvert2/src/GasTexConverter.cpp
+++ b/aconvert2/src/GasTexConverter.cpp
@@ -270,6 +270,14 @@ void GasTexConverter::convert(const automaton::CompactNFA& a, std::ostream& out)
 	out << "\\end{picture}\n";
 }
 
+void GasTexConverter::convert(const automaton::NFTA&, std::ostream&) {
+	//TODO
+}
+
+void GasTexConverter::convert(const automaton::DFTA&, std::ostream&) {
+	//TODO
+}
+
 void GasTexConverter::convert(const automaton::DPDA& a, std::ostream& out) {
 	out << "\\begin{center}\n";
 	out << "\\begin{picture}(,)(,)\n";
@@ -859,6 +867,14 @@ void GasTexConverter::transitions(const automaton::CompactNFA& fsm, std::ostream
 	printTransitionMap(transitionMap, out);
 }
 
+void GasTexConverter::transitions(const automaton::NFTA&, std::ostream&) {
+	//TODO
+}
+
+void GasTexConverter::transitions(const automaton::DFTA&, std::ostream&) {
+	//TODO
+}
+
 void GasTexConverter::transitions(const automaton::DPDA& pda, std::ostream& out) {
 	std::map<std::pair<std::string, std::string>, std::string> transitionMap;
 
@@ -1443,3 +1459,11 @@ void GasTexConverter::Visit(void* data, const automaton::OneTapeDTM& automaton)
 	GasTexConverter::convert(automaton, *((std::ostream*) data));
 }
 
+void GasTexConverter::Visit(void* data, const automaton::NFTA& automaton) const {
+	GasTexConverter::convert(automaton, *((std::ostream*) data));
+}
+
+void GasTexConverter::Visit(void* data, const automaton::DFTA& automaton) const {
+	GasTexConverter::convert(automaton, *((std::ostream*) data));
+}
+
diff --git a/aconvert2/src/GasTexConverter.h b/aconvert2/src/GasTexConverter.h
index 791b28ebf99b70f6c2fff8caff3ae93a6f854fe2..8b8a385d6292410284b6a95faf2fbca0ce387048 100644
--- a/aconvert2/src/GasTexConverter.h
+++ b/aconvert2/src/GasTexConverter.h
@@ -33,6 +33,8 @@ class GasTexConverter : public automaton::VisitableAutomatonBase::const_visitor_
 	void Visit(void*, const automaton::NPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
 	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
 
 	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);
@@ -43,6 +45,8 @@ class GasTexConverter : public automaton::VisitableAutomatonBase::const_visitor_
 	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::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);
 	static void transitions(const automaton::InputDrivenDPDA& pda, std::ostream& out);
@@ -65,6 +69,8 @@ public:
 	static void convert(const automaton::DFA& a, std::ostream& out);
 	static void convert(const automaton::ExtendedNFA& a, std::ostream& out);
 	static void convert(const automaton::CompactNFA& a, std::ostream& out);
+	static void convert(const automaton::NFTA& a, std::ostream& out);
+	static void convert(const automaton::DFTA& a, std::ostream& out);
 	static void convert(const automaton::DPDA& a, std::ostream& out);
 	static void convert(const automaton::SinglePopDPDA& a, std::ostream& out);
 	static void convert(const automaton::InputDrivenDPDA& a, std::ostream& out);
diff --git a/alib2algo/src/automaton/convert/ToGrammar.cpp b/alib2algo/src/automaton/convert/ToGrammar.cpp
index 9c1695445f2d4839a05610e2dca151d504d75b7a..21012d772479a8f332b693a3134c9300485d5add 100644
--- a/alib2algo/src/automaton/convert/ToGrammar.cpp
+++ b/alib2algo/src/automaton/convert/ToGrammar.cpp
@@ -91,6 +91,14 @@ void ToGrammar::Visit(void*, const OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void ToGrammar::Visit(void*, const DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void ToGrammar::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const ToGrammar ToGrammar::TO_GRAMMAR;
 
 } /* namespace convert */
diff --git a/alib2algo/src/automaton/convert/ToGrammar.h b/alib2algo/src/automaton/convert/ToGrammar.h
index 73e094c4e2b55fa11b73dc79318854d1b806ba9f..ecc050680c7fbf59fb3019915f3ed0ae3861cd68 100644
--- a/alib2algo/src/automaton/convert/ToGrammar.h
+++ b/alib2algo/src/automaton/convert/ToGrammar.h
@@ -45,6 +45,8 @@ private:
 	void Visit(void*, const NPDA& automaton) const;
 	void Visit(void*, const SinglePopNPDA& automaton) const;
 	void Visit(void*, const OneTapeDTM& automaton) const;
+	void Visit(void*, const DFTA& automaton) const;
+	void Visit(void*, const NFTA& automaton) const;
 
 	static const ToGrammar TO_GRAMMAR;
 };
diff --git a/alib2algo/src/automaton/determinize/Determinize.cpp b/alib2algo/src/automaton/determinize/Determinize.cpp
index f0609e19367f1be529625c51988be2cc2f622889..a2966075f08862da078a81dcb868b565e72254c4 100644
--- a/alib2algo/src/automaton/determinize/Determinize.cpp
+++ b/alib2algo/src/automaton/determinize/Determinize.cpp
@@ -106,6 +106,16 @@ void Determinize::Visit(void* data, const automaton::OneTapeDTM& automaton) cons
 	out = new automaton::Automaton(automaton);
 }
 
+void Determinize::Visit(void* data, const automaton::NFTA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->determinize(automaton));
+}
+
+void Determinize::Visit(void* data, const automaton::DFTA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(automaton);
+}
+
 const Determinize Determinize::DETERMINIZE;
 
 } /* namespace determinize */
@@ -116,4 +126,5 @@ const Determinize Determinize::DETERMINIZE;
 #include "DeterminizeIDPDAPart.cxx"
 #include "DeterminizeVPAPart.cxx"
 #include "DeterminizeRHDPDAPart.cxx"
+#include "DeterminizeNFTAPart.cxx"
 
diff --git a/alib2algo/src/automaton/determinize/Determinize.h b/alib2algo/src/automaton/determinize/Determinize.h
index 11f97515045b0b5d38509351b8cf807f621656d3..94f936c5f084021345dc073ca89e2ff8522c648c 100644
--- a/alib2algo/src/automaton/determinize/Determinize.h
+++ b/alib2algo/src/automaton/determinize/Determinize.h
@@ -19,6 +19,7 @@
 #include <automaton/PDA/VisiblyPushdownDPDA.h>
 #include <automaton/PDA/RealTimeHeightDeterministicDPDA.h>
 #include <automaton/TM/OneTapeDTM.h>
+#include <automaton/TA/DFTA.h>
 
 #include <exception/AlibException.h>
 
@@ -48,6 +49,8 @@ private:
 	void Visit(void*, const automaton::NPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
 	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
 
 	static const Determinize DETERMINIZE;
 
@@ -65,6 +68,7 @@ public:
 	static automaton::VisiblyPushdownDPDA determinize(const automaton::VisiblyPushdownNPDA& nondeterministic);
 	static automaton::InputDrivenDPDA determinize(const automaton::InputDrivenNPDA& nfa);
 	static automaton::RealTimeHeightDeterministicDPDA determinize(const automaton::RealTimeHeightDeterministicNPDA& nondeterministic);
+	static automaton::DFTA determinize(const automaton::NFTA& nfta);
 };
 
 } /* namespace determinize */
diff --git a/alib2algo/src/automaton/determinize/DeterminizeNFTAPart.cxx b/alib2algo/src/automaton/determinize/DeterminizeNFTAPart.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..897f6057cf01c566536f65ad75ec56809a4dcf6b
--- /dev/null
+++ b/alib2algo/src/automaton/determinize/DeterminizeNFTAPart.cxx
@@ -0,0 +1,99 @@
+/*
+ * NFTADeterminizer.cpp
+ *
+ *  Created on: 30. 3. 2015
+ *	  Author: Stepan Plachy
+ */
+
+#include "common/NFACommon.h"
+
+#include <automaton/TA/NFTA.h>
+#include <deque>
+#include <algorithm>
+
+namespace automaton {
+
+namespace determinize {
+
+std::set<State> getTransitionRightSide(const NFTA & nfta, const alphabet::RankedSymbol & symbol, const std::vector<State> & states) {
+	std::set<State> res;
+	for (const auto & transition : nfta.getTransitions()) {
+		if (transition.first.first != symbol) continue;
+
+		int i = symbol.getRank().getData() - 1;
+		for (; i >= 0; i--)
+			if (!recreateNFAStates(states[i]).count(transition.first.second[i])) break;
+
+		if (i == -1) res.insert(transition.second.begin(), transition.second.end());
+	}
+	return res;
+}
+
+DFTA Determinize::determinize(const NFTA & nfta) {
+	DFTA res;
+	res.setInputSymbols(nfta.getInputAlphabet());
+	for (const auto & state : nfta.getStates()) res.addState(createDFAState({state}));
+	for (const auto & state : nfta.getFinalStates()) res.addFinalState(createDFAState({state}));
+
+	std::deque<State> todo;
+
+	//std::map<std::pair<alphabet::RankedSymbol, std::vector<State> >, std::set<State> > transitions;
+	for (const auto & transition : nfta.getTransitions()) {
+		State state = createDFAState(transition.second);
+		std::vector<State> states;
+		for (const auto & s : transition.first.second) states.push_back(createDFAState({s}));
+		if (transition.second.size() > 1 && res.addState(state)) todo.push_back(state);
+		res.addTransition(transition.first.first, states, state);
+	}
+	
+	while(!todo.empty()) {
+		State currentState = todo.front();
+		todo.pop_front();
+		std::set<State> nftaStates = recreateNFAStates(currentState);
+
+		std::deque<std::pair<std::pair<alphabet::RankedSymbol, std::vector<State> >, State> > transitions;
+		std::deque<int> stops;
+		for (const auto & transition : res.getTransitions()) {
+			transitions.push_back(transition);
+			stops.push_back(0);
+		}
+
+		while(!transitions.empty()) {
+			auto transition = transitions.front();
+			int stop = stops.front();
+			transitions.pop_front();
+			stops.pop_front();
+			const std::vector<State> & states = transition.first.second;
+
+			for (int i = stop; i < (int) states.size(); i++) {
+				if (recreateNFAStates(states[i]).size() != 1) continue;
+				State nftaState = *recreateNFAStates(states[i]).begin();
+				if (nftaStates.count(nftaState)) {
+					std::vector<State> newStates = states;
+					newStates[i] = currentState;
+					
+					std::set<State> newNextStates = getTransitionRightSide(nfta, transition.first.first, newStates);
+					if (!newNextStates.empty()) {
+						State newNextState = createDFAState(newNextStates);
+						if (res.addState(newNextState)) todo.push_back(newNextState);
+						if (res.addTransition(transition.first.first, newStates, newNextState) && i != (int) states.size()-1) {
+							transitions.push_back(std::make_pair(std::make_pair(transition.first.first, newStates), newNextState));
+							stops.push_back(i + 1);
+						}
+					}
+				}
+			}
+		}
+
+		for (const auto & state : nftaStates) {
+			if (nfta.getFinalStates().count(state)) {res.addFinalState(currentState); break;}
+		}
+
+	}
+
+	return res;
+}
+
+} /* namespace determinize */
+
+} /* namespace automaton */
diff --git a/alib2algo/src/automaton/determinize/common/NFACommon.cpp b/alib2algo/src/automaton/determinize/common/NFACommon.cpp
index 16f996c94eee8d371edce31cc69d90aa45c1904c..52d945fdf2255a8378a2c93c140f0b2514782dbf 100644
--- a/alib2algo/src/automaton/determinize/common/NFACommon.cpp
+++ b/alib2algo/src/automaton/determinize/common/NFACommon.cpp
@@ -10,6 +10,7 @@
 
 #include <deque>
 #include <algorithm>
+#include <iostream>
 
 namespace automaton {
 
@@ -24,8 +25,10 @@ automaton::State createDFAState(const std::set<automaton::State>& nfaStates) {
 }
 
 std::set<automaton::State> recreateNFAStates(const automaton::State& dfaState) {
+//	std::cout << dfaState << std::endl;
 	std::set<automaton::State> states;
 	for (const auto& label : static_cast<const label::LabelSetLabel&>(dfaState.getName().getData()).getData()) {
+//		std::cout << label << std::endl;
 		states.insert(automaton::State(label));
 	}
 	return states;
diff --git a/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp b/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp
index 1f3af73a94a0d5be9168ba57d29b0490a12cc630..c8f765befd125f059406dbb0c81bac9702903832 100644
--- a/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp
+++ b/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp
@@ -154,6 +154,14 @@ void AllEpsilonClosure::Visit(void* data, const CompactNFA& automaton) const {
 	out = std::move(this->allEpsilonClosure(automaton));
 }
 
+void AllEpsilonClosure::Visit(void*, const DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void AllEpsilonClosure::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 void AllEpsilonClosure::Visit(void*, const DPDA&) const {
 	throw exception::AlibException("Unsupported automaton type DPDA");
 }
diff --git a/alib2algo/src/automaton/properties/AllEpsilonClosure.h b/alib2algo/src/automaton/properties/AllEpsilonClosure.h
index cdc4323f6b7cbff8b30ac10553399e475da0b120..c7fc6bfeed590b44aa0307418d9809ca26997d9d 100644
--- a/alib2algo/src/automaton/properties/AllEpsilonClosure.h
+++ b/alib2algo/src/automaton/properties/AllEpsilonClosure.h
@@ -39,6 +39,8 @@ private:
 	void Visit(void*, const DFA& automaton) const;
 	void Visit(void*, const ExtendedNFA& automaton) const;
 	void Visit(void*, const CompactNFA& automaton) const;
+	void Visit(void*, const NFTA& automaton) const;
+	void Visit(void*, const DFTA& automaton) const;
 	void Visit(void*, const DPDA& automaton) const;
 	void Visit(void*, const SinglePopDPDA& automaton) const;
 	void Visit(void*, const InputDrivenDPDA& automaton) const;
diff --git a/alib2algo/src/automaton/properties/EpsilonClosure.cpp b/alib2algo/src/automaton/properties/EpsilonClosure.cpp
index 56f3c292f75f1773a74d353f04ee0072d1581a7f..74d1d2df0f405b3fd57f65cc727e96bbfa9bd25b 100644
--- a/alib2algo/src/automaton/properties/EpsilonClosure.cpp
+++ b/alib2algo/src/automaton/properties/EpsilonClosure.cpp
@@ -214,6 +214,14 @@ void EpsilonClosure::Visit(void*, const OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void EpsilonClosure::Visit(void*, const DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void EpsilonClosure::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const EpsilonClosure EpsilonClosure::EPSILON_CLOSURE;
 
 } /* namespace properties */
diff --git a/alib2algo/src/automaton/properties/EpsilonClosure.h b/alib2algo/src/automaton/properties/EpsilonClosure.h
index 2746d25f36dc160c130a1bdeb8d2dabdea0f1b6a..f2dd9f8ab967b0e6f11fdfeafc5745099f32e7b3 100644
--- a/alib2algo/src/automaton/properties/EpsilonClosure.h
+++ b/alib2algo/src/automaton/properties/EpsilonClosure.h
@@ -51,6 +51,8 @@ private:
 	void Visit(void*, const NPDA& automaton) const;
 	void Visit(void*, const SinglePopNPDA& automaton) const;
 	void Visit(void*, const OneTapeDTM& automaton) const;
+	void Visit(void*, const DFTA& automaton) const;
+	void Visit(void*, const NFTA& automaton) const;
 
 	static const EpsilonClosure EPSILON_CLOSURE;
 };
diff --git a/alib2algo/src/automaton/properties/ReachableStates.cpp b/alib2algo/src/automaton/properties/ReachableStates.cpp
index 868d0b7a9ac1a3a9657d93f9a39b0de0a4783eac..b42f1bfc77e66e07205c0994d4dade589b0eec9d 100644
--- a/alib2algo/src/automaton/properties/ReachableStates.cpp
+++ b/alib2algo/src/automaton/properties/ReachableStates.cpp
@@ -141,6 +141,14 @@ void ReachableStates::Visit(void* data, const CompactNFA& automaton) const {
 	out = std::move(this->reachableStates(automaton));
 }
 
+void ReachableStates::Visit(void*, const DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void ReachableStates::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 void ReachableStates::Visit(void*, const DPDA&) const {
 	throw exception::AlibException("Unsupported automaton type DPDA");
 }
diff --git a/alib2algo/src/automaton/properties/ReachableStates.h b/alib2algo/src/automaton/properties/ReachableStates.h
index a3f8559c25f8806dcfddbae73fed023fdaf85220..88ede0f89d0eb7c0e91aa813b572da989ca1a319 100644
--- a/alib2algo/src/automaton/properties/ReachableStates.h
+++ b/alib2algo/src/automaton/properties/ReachableStates.h
@@ -47,6 +47,8 @@ private:
 	void Visit(void*, const NPDA& automaton) const;
 	void Visit(void*, const SinglePopNPDA& automaton) const;
 	void Visit(void*, const OneTapeDTM& automaton) const;
+	void Visit(void*, const DFTA& automaton) const;
+	void Visit(void*, const NFTA& automaton) const;
 
 	static const ReachableStates REACHABLE_STATES;
 };
diff --git a/alib2algo/src/automaton/properties/UsefullStates.cpp b/alib2algo/src/automaton/properties/UsefullStates.cpp
index c62908e6c58f7683577298c822ab22cf76af160b..d02f690297172e90a1d699f0039e035d21c505af 100644
--- a/alib2algo/src/automaton/properties/UsefullStates.cpp
+++ b/alib2algo/src/automaton/properties/UsefullStates.cpp
@@ -156,6 +156,14 @@ void UsefullStates::Visit(void*, const OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void UsefullStates::Visit(void*, const DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void UsefullStates::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const UsefullStates UsefullStates::USEFULL_STATES;
 
 } /* namespace properties */
diff --git a/alib2algo/src/automaton/properties/UsefullStates.h b/alib2algo/src/automaton/properties/UsefullStates.h
index 5e8b745df27ce0d3361759381b213c36f08d7e47..3fa2b58735497d7ebd893cdb24439bd44f52e83e 100644
--- a/alib2algo/src/automaton/properties/UsefullStates.h
+++ b/alib2algo/src/automaton/properties/UsefullStates.h
@@ -47,6 +47,8 @@ private:
 	void Visit(void*, const NPDA& automaton) const;
 	void Visit(void*, const SinglePopNPDA& automaton) const;
 	void Visit(void*, const OneTapeDTM& automaton) const;
+	void Visit(void*, const DFTA& automaton) const;
+	void Visit(void*, const NFTA& automaton) const;
 
 	static const UsefullStates USEFULL_STATES;
 };
diff --git a/alib2algo/src/automaton/run/Accept.cpp b/alib2algo/src/automaton/run/Accept.cpp
index be35e5ae2dd0ebea3f98a29b83ab8541af9eb29e..36682d9f9f19d281cd8e5745f5cde25f86a2868d 100644
--- a/alib2algo/src/automaton/run/Accept.cpp
+++ b/alib2algo/src/automaton/run/Accept.cpp
@@ -10,6 +10,8 @@
 #include <automaton/FSM/DFA.h>
 #include <automaton/FSM/NFA.h>
 #include <automaton/PDA/DPDA.h>
+#include <automaton/TA/DFTA.h>
+#include <automaton/TA/NFTA.h>
 
 #include <deque>
 
@@ -17,8 +19,22 @@ namespace automaton {
 
 namespace run {
 
+bool Accept::accept(const automaton::Automaton& automaton, const alib::Object& object) {
+	std::pair<const alib::Object*, bool> data(&object, false);
+	automaton.getData().Accept((void*) &data, Accept::ACCEPT);
+	return data.second;
+}
+
 bool Accept::accept(const automaton::Automaton& automaton, const string::LinearString& string) {
-	std::pair<const string::LinearString*, bool> data(&string, false);
+	alib::Object obj(string);
+	std::pair<const alib::Object*, bool> data(&obj, false);
+	automaton.getData().Accept((void*) &data, Accept::ACCEPT);
+	return data.second;
+}
+
+bool Accept::accept(const automaton::Automaton& automaton, const tree::RankedTree& tree) {
+	alib::Object obj(tree);
+	std::pair<const alib::Object*, bool> data(&obj, false);
 	automaton.getData().Accept((void*) &data, Accept::ACCEPT);
 	return data.second;
 }
@@ -34,6 +50,51 @@ bool Accept::accept(const automaton::DFA& automaton, const string::LinearString&
 	return automaton.getFinalStates().count(state);
 }
 
+State Accept::calculateState(const automaton::DFTA& automaton, const tree::RankedNode & node) {
+	std::vector<State> states;
+	states.reserve(node.getSymbol().getRank().getData());
+	for (const auto & child : node.getChildren()) {
+		State state = calculateState(automaton, *child);
+		if (state == FAILSTATE) return FAILSTATE;
+		states.push_back(state);
+	}
+	const auto & it = automaton.getTransitions().find(std::make_pair(node.getSymbol(), states));
+	if (it == automaton.getTransitions().end()) return FAILSTATE;
+	return it -> second;
+}
+
+bool Accept::accept(const automaton::DFTA& automaton, const tree::RankedTree& tree) {
+	return automaton.getFinalStates().count(calculateState(automaton, tree.getRoot()));
+}
+
+std::set<State> calculateStates(const automaton::NFTA& automaton, const tree::RankedNode & node) {
+	std::vector<std::set<State> > states;
+	states.reserve(node.getSymbol().getRank().getData());
+	for (const auto & child : node.getChildren()) {
+		std::set<State> childStates = calculateStates(automaton, *child);
+		if (childStates.empty()) return childStates;
+		states.push_back(childStates);
+	}
+
+	std::set<State> res;
+	for (const auto & transition : automaton.getTransitions()) {
+		if (transition.first.first != node.getSymbol()) continue;
+		int i = transition.first.first.getRank().getData() - 1;
+		for(; i >= 0 ; i--)
+			if (!states[i].count(transition.first.second[i])) break;
+		
+		if (i == -1) res.insert(transition.second.begin(), transition.second.end());
+	}
+	return res;
+}
+
+bool Accept::accept(const automaton::NFTA& automaton, const tree::RankedTree & tree) {
+	std::set<State> res = calculateStates(automaton, tree.getRoot());
+	for (auto & state : res)
+		if (automaton.getFinalStates().count(state)) return true;
+	return false;
+}
+
 bool recursiveAccept(const automaton::NFA& automaton, const automaton::State& state, const string::LinearString& string) {
 	if( string.getContent().empty( ) )
 		return automaton.getFinalStates().count( state );
@@ -101,13 +162,13 @@ void Accept::Visit(void*, const automaton::MultiInitialStateNFA& ) const {
 }
 
 void Accept::Visit(void* data, const automaton::NFA& automaton) const {
-	std::pair<const string::LinearString*, bool> & res = *((std::pair<const string::LinearString*, bool>*) data);
-	res.second = this->accept(automaton, *res.first);
+	std::pair<const alib::Object*, bool> & res = *((std::pair<const alib::Object*, bool>*) data);
+	res.second = this->accept(automaton, static_cast<const string::LinearString&>(res.first->getData()));
 }
 
 void Accept::Visit(void* data, const automaton::DFA& automaton) const {
-	std::pair<const string::LinearString*, bool> & res = *((std::pair<const string::LinearString*, bool>*) data);
-	res.second = this->accept(automaton, *res.first);
+	std::pair<const alib::Object*, bool> & res = *((std::pair<const alib::Object*, bool>*) data);
+	res.second = this->accept(automaton, static_cast<const string::LinearString&>(res.first->getData()));
 }
 
 void Accept::Visit(void*, const automaton::ExtendedNFA& ) const {
@@ -119,8 +180,8 @@ void Accept::Visit(void*, const automaton::CompactNFA& ) const {
 }
 
 void Accept::Visit(void* data, const DPDA& automaton) const {
-	std::pair<const string::LinearString*, bool> & res = *((std::pair<const string::LinearString*, bool>*) data);
-	res.second = this->accept(automaton, *res.first);
+	std::pair<const alib::Object*, bool> & res = *((std::pair<const alib::Object*, bool>*) data);
+	res.second = this->accept(automaton, static_cast<const string::LinearString&>(res.first->getData()));
 }
 
 void Accept::Visit(void*, const SinglePopDPDA&) const {
@@ -163,6 +224,16 @@ void Accept::Visit(void*, const OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void Accept::Visit(void* data, const automaton::DFTA& automaton) const {
+	std::pair<const alib::Object*, bool> & res = *((std::pair<const alib::Object*, bool>*) data);
+	res.second = this->accept(automaton, static_cast<const tree::RankedTree&>(res.first->getData()));
+}
+
+void Accept::Visit(void* data, const NFTA& automaton) const {
+	std::pair<const alib::Object*, bool> & res = *((std::pair<const alib::Object*, bool>*) data);
+	res.second = this->accept(automaton, static_cast<const tree::RankedTree&>(res.first->getData()));
+}
+
 const Accept Accept::ACCEPT;
 
 } /* namespace run */
diff --git a/alib2algo/src/automaton/run/Accept.h b/alib2algo/src/automaton/run/Accept.h
index e1cc13d7aca0af5e47c361e5c6420f76175bc9be..ed451178ce363eaddf8d5d975179f2e639eedbc0 100644
--- a/alib2algo/src/automaton/run/Accept.h
+++ b/alib2algo/src/automaton/run/Accept.h
@@ -9,7 +9,9 @@
 #define _AUTOMATON_ACCEPT_H__
 
 #include <automaton/Automaton.h>
+#include <object/Object.h>
 #include <string/LinearString.h>
+#include <tree/RankedTree/RankedTree.h>
 
 namespace automaton {
 
@@ -21,12 +23,18 @@ public:
 	 * Performs conversion.
 	 * @return left regular grammar equivalent to source automaton.
 	 */
+	static bool accept(const automaton::Automaton& automaton, const alib::Object& object);
 	static bool accept(const automaton::Automaton& automaton, const string::LinearString& string);
+	static bool accept(const automaton::Automaton& automaton, const tree::RankedTree& string);
 
 	static bool accept(const automaton::DFA& automaton, const string::LinearString& string);
 	static bool accept(const automaton::NFA& automaton, const string::LinearString& string);
 	static bool accept(const automaton::DPDA& 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);
 private:
+	static State calculateState(const automaton::DFTA& automaton, const tree::RankedNode & node);
+
 	void Visit(void*, const EpsilonNFA& automaton) const;
 	void Visit(void*, const MultiInitialStateNFA& automaton) const;
 	void Visit(void*, const NFA& automaton) const;
@@ -44,6 +52,8 @@ private:
 	void Visit(void*, const NPDA& automaton) const;
 	void Visit(void*, const SinglePopNPDA& automaton) const;
 	void Visit(void*, const OneTapeDTM& automaton) const;
+	void Visit(void*, const DFTA& automaton) const;
+	void Visit(void*, const NFTA& automaton) const;
 
 	static const Accept ACCEPT;
 };
diff --git a/alib2algo/src/automaton/run/Occurrences.cpp b/alib2algo/src/automaton/run/Occurrences.cpp
index 6e92814c32346571efe6f3771fe43ef32089f983..a07b512feb40b3e08ffc979dc00774149c54e4a3 100644
--- a/alib2algo/src/automaton/run/Occurrences.cpp
+++ b/alib2algo/src/automaton/run/Occurrences.cpp
@@ -10,6 +10,7 @@
 #include <automaton/FSM/DFA.h>
 #include <automaton/FSM/NFA.h>
 #include <automaton/PDA/DPDA.h>
+#include <automaton/TA/DFTA.h>
 
 #include <deque>
 
@@ -17,8 +18,22 @@ namespace automaton {
 
 namespace run {
 
+std::set<unsigned> Occurrences::occurrences(const automaton::Automaton& automaton, const alib::Object& object) {
+	std::pair<const alib::Object*, std::set<unsigned>> data(&object, {});
+	automaton.getData().Accept((void*) &data, Occurrences::OCCURRENCES);
+	return data.second;
+}
+
 std::set<unsigned> Occurrences::occurrences(const automaton::Automaton& automaton, const string::LinearString& string) {
-	std::pair<const string::LinearString*, std::set<unsigned>> data(&string, {});
+	alib::Object obj(string);
+	std::pair<const alib::Object*, std::set<unsigned>> data(&obj, {});
+	automaton.getData().Accept((void*) &data, Occurrences::OCCURRENCES);
+	return data.second;
+}
+
+std::set<unsigned> Occurrences::occurrences(const automaton::Automaton& automaton, const tree::RankedTree& tree) {
+	alib::Object obj(tree);
+	std::pair<const alib::Object*, std::set<unsigned>> data(&obj, {});
 	automaton.getData().Accept((void*) &data, Occurrences::OCCURRENCES);
 	return data.second;
 }
@@ -49,6 +64,32 @@ std::set<unsigned> Occurrences::occurrences(const automaton::DFA& automaton, con
 	return occ;
 }
 
+State Occurrences::occurences(const automaton::DFTA & automaton, const tree::RankedNode & node, std::set<unsigned> & occ, unsigned & i) {
+	std::vector<State> states;
+	unsigned tmp = i;
+	i++;
+	states.reserve(node.getSymbol().getRank().getData());
+	bool fail = false;
+	for (const auto & child : node.getChildren()) {
+		State state = occurences(automaton, *child, occ, i);
+		if (state == FAILSTATE) fail = true;
+		else if (!fail) states.push_back(state);
+	}
+	if (fail) return FAILSTATE;
+	const auto & it = automaton.getTransitions().find(std::make_pair(node.getSymbol(), states));
+	if (it == automaton.getTransitions().end()) return FAILSTATE;
+	State state = it -> second;
+	if (automaton.getFinalStates().count(state)) occ.insert(tmp);
+	return state;
+}
+
+std::set<unsigned> Occurrences::occurrences(const automaton::DFTA& automaton, const tree::RankedTree & tree) {
+	std::set<unsigned> occ;
+	unsigned i = 0;
+	occurences(automaton, tree.getRoot(), occ, i);
+	return occ;
+}
+
 std::set<unsigned> Occurrences::occurrences(const automaton::DPDA& automaton, const string::LinearString& string) {
 	automaton::State state = automaton.getInitialState();
 	std::deque<alphabet::Symbol> pushdownStore;
@@ -111,8 +152,8 @@ void Occurrences::Visit(void*, const automaton::NFA& ) const {
 }
 
 void Occurrences::Visit(void* data, const automaton::DFA& automaton) const {
-	std::pair<const string::LinearString*, std::set<unsigned>> & res = *((std::pair<const string::LinearString*, std::set<unsigned>>*) data);
-	res.second = this->occurrences(automaton, *res.first);
+	std::pair<const alib::Object*, std::set<unsigned>> & res = *((std::pair<const alib::Object*, std::set<unsigned>>*) data);
+	res.second = this->occurrences(automaton, static_cast<const string::LinearString&>(res.first->getData()));
 }
 
 void Occurrences::Visit(void*, const automaton::ExtendedNFA& ) const {
@@ -124,8 +165,8 @@ void Occurrences::Visit(void*, const automaton::CompactNFA& ) const {
 }
 
 void Occurrences::Visit(void* data, const DPDA& automaton) const {
-	std::pair<const string::LinearString*, std::set<unsigned>> & res = *((std::pair<const string::LinearString*, std::set<unsigned>>*) data);
-	res.second = this->occurrences(automaton, *res.first);
+	std::pair<const alib::Object*, std::set<unsigned>> & res = *((std::pair<const alib::Object*, std::set<unsigned>>*) data);
+	res.second = this->occurrences(automaton, static_cast<const string::LinearString&>(res.first->getData()));
 }
 
 void Occurrences::Visit(void*, const SinglePopDPDA&) const {
@@ -168,6 +209,15 @@ void Occurrences::Visit(void*, const OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void Occurrences::Visit(void* data, const automaton::DFTA& automaton) const {
+	std::pair<const alib::Object*, std::set<unsigned>> & res = *((std::pair<const alib::Object*, std::set<unsigned>>*) data);
+	res.second = this->occurrences(automaton, static_cast<const tree::RankedTree&>(res.first->getData()));
+}
+
+void Occurrences::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const Occurrences Occurrences::OCCURRENCES;
 
 } /* namespace run */
diff --git a/alib2algo/src/automaton/run/Occurrences.h b/alib2algo/src/automaton/run/Occurrences.h
index 7481e1033a4d0123a343a021cadcb4fbbc2d81de..dc15fb58485991fa00f81e2117c77ce6382e25ee 100644
--- a/alib2algo/src/automaton/run/Occurrences.h
+++ b/alib2algo/src/automaton/run/Occurrences.h
@@ -9,7 +9,9 @@
 #define _AUTOMATON_OCCURRENCES_H__
 
 #include <automaton/Automaton.h>
+#include <object/Object.h>
 #include <string/LinearString.h>
+#include <tree/RankedTree/RankedTree.h>
 
 namespace automaton {
 
@@ -21,11 +23,16 @@ public:
 	 * Performs conversion.
 	 * @return left regular grammar equivalent to source automaton.
 	 */
+	static std::set<unsigned> occurrences(const automaton::Automaton& automaton, const alib::Object& object);
 	static std::set<unsigned> occurrences(const automaton::Automaton& automaton, const string::LinearString& string);
+	static std::set<unsigned> occurrences(const automaton::Automaton& automaton, const tree::RankedTree& string);
 
 	static std::set<unsigned> occurrences(const automaton::DFA& automaton, const string::LinearString& string);
 	static std::set<unsigned> occurrences(const automaton::DPDA& automaton, const string::LinearString& string);
+	static std::set<unsigned> occurrences(const automaton::DFTA& automaton, const tree::RankedTree & tree);
 private:
+	static State occurences(const automaton::DFTA & automaton, const tree::RankedNode & node, std::set<unsigned> & occ, unsigned & i);
+
 	void Visit(void*, const EpsilonNFA& automaton) const;
 	void Visit(void*, const MultiInitialStateNFA& automaton) const;
 	void Visit(void*, const NFA& automaton) const;
@@ -43,6 +50,8 @@ private:
 	void Visit(void*, const NPDA& automaton) const;
 	void Visit(void*, const SinglePopNPDA& automaton) const;
 	void Visit(void*, const OneTapeDTM& automaton) const;
+	void Visit(void*, const DFTA& automaton) const;
+	void Visit(void*, const NFTA& automaton) const;
 
 	static const Occurrences OCCURRENCES;
 };
diff --git a/alib2algo/src/automaton/run/Result.cpp b/alib2algo/src/automaton/run/Result.cpp
index 893125a1cca97f82034843fa145fe6ad85e0a37f..0194f931c5958dbf6b7548a4cc425ef053ad9b9c 100644
--- a/alib2algo/src/automaton/run/Result.cpp
+++ b/alib2algo/src/automaton/run/Result.cpp
@@ -9,6 +9,7 @@
 #include <exception/AlibException.h>
 #include <automaton/FSM/DFA.h>
 #include <automaton/PDA/DPDA.h>
+#include <automaton/TA/DFTA.h>
 #include <label/LabelSetLabel.h>
 
 #include <deque>
@@ -17,8 +18,8 @@ namespace automaton {
 
 namespace run {
 
-label::Label Result::result(const automaton::Automaton& automaton, const string::LinearString& string) {
-	std::pair<const string::LinearString*, label::Label*> data(&string, NULL);
+label::Label Result::result(const automaton::Automaton& automaton, const alib::Object& object) {
+	std::pair<const alib::Object*, label::Label*> data(&object, NULL);
 	automaton.getData().Accept((void*) &data, Result::RESULT);
 	label::Label res = std::move(*data.second);
 	delete data.second;
@@ -74,6 +75,24 @@ label::Label Result::result(const automaton::DPDA& automaton, const string::Line
 	}
 }
 
+automaton::State Result::calculateState(const automaton::DFTA& automaton, const tree::RankedNode & node) {
+	std::vector<automaton::State> states;
+	states.reserve(node.getSymbol().getRank().getData());
+	for (const auto & child : node.getChildren()) {
+		automaton::State state = calculateState(automaton, *child);
+		if (state == FAILSTATE) return FAILSTATE;
+		states.push_back(state);
+	}
+	const auto & it = automaton.getTransitions().find(std::make_pair(node.getSymbol(), states));
+	if (it == automaton.getTransitions().end()) return FAILSTATE;
+	return it -> second;
+}
+
+label::Label Result::result(const automaton::DFTA& automaton, const tree::RankedTree& tree) {
+	State state = calculateState(automaton, tree.getRoot());
+	return state.getName();
+}
+
 void Result::Visit(void*, const automaton::EpsilonNFA& ) const {
 	throw exception::AlibException("Unsupported automaton type EpsilonNFA");
 }
@@ -87,8 +106,8 @@ void Result::Visit(void*, const automaton::NFA& ) const {
 }
 
 void Result::Visit(void* data, const automaton::DFA& automaton) const {
-	std::pair<const string::LinearString*, label::Label*> & res = *((std::pair<const string::LinearString*, label::Label*>*) data);
-	res.second = new label::Label(std::move(this->result(automaton, *res.first)));
+	std::pair<const alib::Object*, label::Label*> & res = *((std::pair<const alib::Object*,  label::Label*>*) data);
+	res.second = new label::Label(std::move(this->result(automaton, static_cast<const string::LinearString&>(res.first->getData()))));
 }
 
 void Result::Visit(void*, const automaton::ExtendedNFA& ) const {
@@ -100,8 +119,8 @@ void Result::Visit(void*, const automaton::CompactNFA& ) const {
 }
 
 void Result::Visit(void* data, const DPDA& automaton) const {
-	std::pair<const string::LinearString*, label::Label*> & res = *((std::pair<const string::LinearString*, label::Label*>*) data);
-	res.second = new label::Label(std::move(this->result(automaton, *res.first)));
+	std::pair<const alib::Object*, label::Label*> & res = *((std::pair<const alib::Object*,  label::Label*>*) data);
+	res.second = new label::Label(std::move(this->result(automaton, static_cast<const string::LinearString&>(res.first->getData()))));
 }
 
 void Result::Visit(void*, const SinglePopDPDA&) const {
@@ -144,6 +163,15 @@ void Result::Visit(void*, const OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void Result::Visit(void* data, const automaton::DFTA& automaton) const {
+	std::pair<const alib::Object*, label::Label*> & res = *((std::pair<const alib::Object*,  label::Label*>*) data);
+	res.second = new label::Label(std::move(this->result(automaton, static_cast<const tree::RankedTree&>(res.first->getData()))));
+}
+
+void Result::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const Result Result::RESULT;
 
 } /* namespace run */
diff --git a/alib2algo/src/automaton/run/Result.h b/alib2algo/src/automaton/run/Result.h
index 15fd71dbb883074e041b9bab6da531585c4321f4..acdebc95b55c449b71ec25851149afb401cfa7ed 100644
--- a/alib2algo/src/automaton/run/Result.h
+++ b/alib2algo/src/automaton/run/Result.h
@@ -10,7 +10,9 @@
 
 #include <automaton/Automaton.h>
 #include <string/LinearString.h>
+#include <object/Object.h>
 #include <label/Label.h>
+#include <tree/RankedTree/RankedTree.h>
 
 namespace automaton {
 
@@ -22,12 +24,14 @@ public:
 	 * Performs conversion.
 	 * @return left regular grammar equivalent to source automaton.
 	 */
-	static label::Label result(const automaton::Automaton& automaton, const string::LinearString& string);
+	static label::Label result(const automaton::Automaton& automaton, const alib::Object& object);
 
 	static label::Label result(const automaton::DFA& automaton, const string::LinearString& string);
-	static label::Label result(const automaton::NFA& automaton, const string::LinearString& string);
 	static label::Label result(const automaton::DPDA& automaton, const string::LinearString& string);
+	static label::Label result(const automaton::DFTA& automaton, const tree::RankedTree & tree);
 private:
+	static automaton::State calculateState(const automaton::DFTA& automaton, const tree::RankedNode & node);
+
 	void Visit(void*, const EpsilonNFA& automaton) const;
 	void Visit(void*, const MultiInitialStateNFA& automaton) const;
 	void Visit(void*, const NFA& automaton) const;
@@ -45,6 +49,8 @@ private:
 	void Visit(void*, const NPDA& automaton) const;
 	void Visit(void*, const SinglePopNPDA& automaton) const;
 	void Visit(void*, const OneTapeDTM& automaton) const;
+	void Visit(void*, const DFTA& automaton) const;
+	void Visit(void*, const NFTA& automaton) const;
 
 	static const Result RESULT;
 };
diff --git a/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.cpp b/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.cpp
index cfdc6b57039742c47ab15dccb5e448762079849b..13c329b5cf7267acdde8f21748125655842244b7 100644
--- a/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.cpp
+++ b/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.cpp
@@ -146,6 +146,14 @@ void EpsilonRemoverIncoming::Visit(void*, const automaton::OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void EpsilonRemoverIncoming::Visit(void*, const automaton::DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void EpsilonRemoverIncoming::Visit(void*, const automaton::NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const EpsilonRemoverIncoming EpsilonRemoverIncoming::EPSILON_REMOVER_INCOMING;
 
 } /* namespace simplify */
diff --git a/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.h b/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.h
index 424a9e23bca9b3d9dc88bb72ce55b813f74b0fdb..8a79bb5d25ab83abcabb847f2aab047d39fb6aa8 100644
--- a/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.h
+++ b/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.h
@@ -53,6 +53,8 @@ private:
 	void Visit(void*, const automaton::NPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
 	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
 
 	static const EpsilonRemoverIncoming EPSILON_REMOVER_INCOMING;
 };
diff --git a/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.cpp b/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.cpp
index 966278070280652708469d0a7ba6de9bce5b3ce5..c4864600b21da29e1f1b69d8dc367b6233598774 100644
--- a/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.cpp
+++ b/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.cpp
@@ -139,6 +139,14 @@ void EpsilonRemoverOutgoing::Visit(void*, const automaton::OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void EpsilonRemoverOutgoing::Visit(void*, const automaton::DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void EpsilonRemoverOutgoing::Visit(void*, const automaton::NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const EpsilonRemoverOutgoing EpsilonRemoverOutgoing::EPSILON_REMOVER_OUTGOING;
 
 } /* namespace simplify */
diff --git a/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.h b/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.h
index 86f3201e500973adbc915b6652c7150a60a4595e..e76b99a711172295f2b4512593c6c821202df102 100644
--- a/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.h
+++ b/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.h
@@ -53,6 +53,8 @@ private:
 	void Visit(void*, const automaton::NPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
 	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
 
 	static const EpsilonRemoverOutgoing EPSILON_REMOVER_OUTGOING;
 };
diff --git a/alib2algo/src/automaton/simplify/Minimize.cpp b/alib2algo/src/automaton/simplify/Minimize.cpp
index 2bd6b930bc7ec8d378d94f968b9f88d59f903453..62e6bffa9ab5c77154cfa6909337a746b424250e 100644
--- a/alib2algo/src/automaton/simplify/Minimize.cpp
+++ b/alib2algo/src/automaton/simplify/Minimize.cpp
@@ -208,6 +208,14 @@ void Minimize::Visit(void*, const automaton::OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void Minimize::Visit(void*, const automaton::DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void Minimize::Visit(void*, const automaton::NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const Minimize Minimize::MINIMIZE;
 
 } /* namespace simplify */
diff --git a/alib2algo/src/automaton/simplify/Minimize.h b/alib2algo/src/automaton/simplify/Minimize.h
index 00a68b654657583da3cb57c39b770da79c031cd5..d71753aa99a1d7c3896ee84e636b1444a3a24adc 100644
--- a/alib2algo/src/automaton/simplify/Minimize.h
+++ b/alib2algo/src/automaton/simplify/Minimize.h
@@ -42,6 +42,8 @@ protected:
 	void Visit(void*, const automaton::NPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
 	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
 
 	static const Minimize MINIMIZE;
 };
diff --git a/alib2algo/src/automaton/simplify/Normalize.cpp b/alib2algo/src/automaton/simplify/Normalize.cpp
index 83edf5d8b303a5b5eba533f7aadb58f576811295..6dd62b0101444f4454eee51bc8b709497ee6b762 100644
--- a/alib2algo/src/automaton/simplify/Normalize.cpp
+++ b/alib2algo/src/automaton/simplify/Normalize.cpp
@@ -238,6 +238,14 @@ void Normalize::Visit(void*, const automaton::OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void Normalize::Visit(void*, const automaton::DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void Normalize::Visit(void*, const automaton::NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const Normalize Normalize::NORMALIZE;
 
 } /* namespace simplify */
diff --git a/alib2algo/src/automaton/simplify/Normalize.h b/alib2algo/src/automaton/simplify/Normalize.h
index e6bad87ff6780479fc6a7f32a6955e177fce12ec..791ae5a70dcb913b5c1e38913f68746076ebda4e 100644
--- a/alib2algo/src/automaton/simplify/Normalize.h
+++ b/alib2algo/src/automaton/simplify/Normalize.h
@@ -45,6 +45,8 @@ protected:
 	void Visit(void*, const automaton::NPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
 	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
 
 	static const Normalize NORMALIZE;
 };
diff --git a/alib2algo/src/automaton/simplify/Rename.cpp b/alib2algo/src/automaton/simplify/Rename.cpp
index c44b4ba020d4624ea3a26816575a8059a55b3ac9..30f84f8c40b95635c3d6c9c2eb0b961b8676bf7f 100644
--- a/alib2algo/src/automaton/simplify/Rename.cpp
+++ b/alib2algo/src/automaton/simplify/Rename.cpp
@@ -357,6 +357,14 @@ void Rename::Visit(void*, const automaton::OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void Rename::Visit(void*, const automaton::DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void Rename::Visit(void*, const automaton::NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const Rename Rename::RENAME;
 
 } /* namespace simplify */
diff --git a/alib2algo/src/automaton/simplify/Rename.h b/alib2algo/src/automaton/simplify/Rename.h
index e3eb0281ec7099a766b41a0ae7898e88999cd93a..9312f94ed88010759c627c3e577867aaddbe496b 100644
--- a/alib2algo/src/automaton/simplify/Rename.h
+++ b/alib2algo/src/automaton/simplify/Rename.h
@@ -53,6 +53,8 @@ protected:
 	void Visit(void*, const automaton::NPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
 	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
 
 	static const Rename RENAME;
 };
diff --git a/alib2algo/src/automaton/simplify/SingleInitialState.cpp b/alib2algo/src/automaton/simplify/SingleInitialState.cpp
index 4712810c6e5360e8f4d6b9df79225abba601a0d5..d5abc7b46e3b938bd3232def8a5e55c0fc1ff377 100644
--- a/alib2algo/src/automaton/simplify/SingleInitialState.cpp
+++ b/alib2algo/src/automaton/simplify/SingleInitialState.cpp
@@ -166,6 +166,14 @@ void SingleInitialState::Visit(void*, const OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void SingleInitialState::Visit(void*, const automaton::DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void SingleInitialState::Visit(void*, const automaton::NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const SingleInitialState SingleInitialState::SINGLE_INITIAL_STATE;
 
 } /* namespace simplify */
diff --git a/alib2algo/src/automaton/simplify/SingleInitialState.h b/alib2algo/src/automaton/simplify/SingleInitialState.h
index 65a0c20cfbb7825897610aed6512cf13ab6ff40f..881fe3526979ce7f2ac7b7a9e0540f7e92c13f30 100644
--- a/alib2algo/src/automaton/simplify/SingleInitialState.h
+++ b/alib2algo/src/automaton/simplify/SingleInitialState.h
@@ -52,6 +52,8 @@ private:
 	void Visit(void*, const NPDA& automaton) const;
 	void Visit(void*, const SinglePopNPDA& automaton) const;
 	void Visit(void*, const OneTapeDTM& automaton) const;
+	void Visit(void*, const DFTA& automaton) const;
+	void Visit(void*, const NFTA& automaton) const;
 
 	static const SingleInitialState SINGLE_INITIAL_STATE;
 };
diff --git a/alib2algo/src/automaton/simplify/Trim.cpp b/alib2algo/src/automaton/simplify/Trim.cpp
index a2cef7225aeecd92c85033f1a2954456804e39cc..16eba371dfc8ad255767e594958a6289e53b0085 100644
--- a/alib2algo/src/automaton/simplify/Trim.cpp
+++ b/alib2algo/src/automaton/simplify/Trim.cpp
@@ -117,6 +117,14 @@ void Trim::Visit(void*, const automaton::OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void Trim::Visit(void*, const automaton::DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void Trim::Visit(void*, const automaton::NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const Trim Trim::TRIM;
 
 } /* namespace simplify */
diff --git a/alib2algo/src/automaton/simplify/Trim.h b/alib2algo/src/automaton/simplify/Trim.h
index 7b6ce047bdb337cc7f95291bc064ac14a281f365..2cb8fd2b5f787513f4316e51a525f35b195411e3 100644
--- a/alib2algo/src/automaton/simplify/Trim.h
+++ b/alib2algo/src/automaton/simplify/Trim.h
@@ -45,6 +45,8 @@ private:
 	void Visit(void*, const automaton::NPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
 	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
 
 	static const Trim TRIM;
 };
diff --git a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp
index b6a5312dd40f37ba3e50841bbdb2a6d86efc8c01..1e05460cc13e952e72f73a8cfebe6b06ee79396d 100644
--- a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp
+++ b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp
@@ -193,6 +193,14 @@ void UnreachableStatesRemover::Visit(void*, const automaton::OneTapeDTM&) const
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void UnreachableStatesRemover::Visit(void*, const automaton::DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void UnreachableStatesRemover::Visit(void*, const automaton::NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const UnreachableStatesRemover UnreachableStatesRemover::UNREACHABLE_STATES_REMOVER;
 
 } /* namespace simplify */
diff --git a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h
index 3f2d436d223a1a4f3f51923b5944e449aae1f17a..b584132ddac6947a1a59cf348df23a18310de6c3 100644
--- a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h
+++ b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h
@@ -45,6 +45,8 @@ private:
 	void Visit(void*, const automaton::NPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
 	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
 
 	static const UnreachableStatesRemover UNREACHABLE_STATES_REMOVER;
 };
diff --git a/alib2algo/src/automaton/simplify/UselessStatesRemover.cpp b/alib2algo/src/automaton/simplify/UselessStatesRemover.cpp
index 5b843eacdd4a203a4e7d9367278a2a189ef69322..b0881342918b6d72964a783f97383406abbcf5e8 100644
--- a/alib2algo/src/automaton/simplify/UselessStatesRemover.cpp
+++ b/alib2algo/src/automaton/simplify/UselessStatesRemover.cpp
@@ -202,6 +202,14 @@ void UselessStatesRemover::Visit(void*, const automaton::OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void UselessStatesRemover::Visit(void*, const automaton::DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void UselessStatesRemover::Visit(void*, const automaton::NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const UselessStatesRemover UselessStatesRemover::USELESS_STATES_REMOVER;
 
 } /* namespace simplify */
diff --git a/alib2algo/src/automaton/simplify/UselessStatesRemover.h b/alib2algo/src/automaton/simplify/UselessStatesRemover.h
index ba26622ab9b79603731120648ac3135a766f4142..38c86626323929881f93da667a1eccec50ad6bee 100644
--- a/alib2algo/src/automaton/simplify/UselessStatesRemover.h
+++ b/alib2algo/src/automaton/simplify/UselessStatesRemover.h
@@ -45,6 +45,8 @@ private:
 	void Visit(void*, const automaton::NPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
 	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
 
 	static const UselessStatesRemover USELESS_STATES_REMOVER;
 };
diff --git a/alib2algo/src/automaton/transform/AutomataConcatenation.cpp b/alib2algo/src/automaton/transform/AutomataConcatenation.cpp
index b935f1892d0d71cd3b6068f809f32117287da257..fc3bbd95b4295cb138c0d297d7a827f29b73553d 100644
--- a/alib2algo/src/automaton/transform/AutomataConcatenation.cpp
+++ b/alib2algo/src/automaton/transform/AutomataConcatenation.cpp
@@ -205,6 +205,16 @@ void AutomataConcatenation::Visit(void*, const automaton::OneTapeDTM&, const aut
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void AutomataConcatenation::Visit(void*, const automaton::DFTA&, const automaton::DFTA&) const
+{
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void AutomataConcatenation::Visit(void*, const automaton::NFTA&, const automaton::NFTA&) const
+{
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const AutomataConcatenation AutomataConcatenation::AUTOMATA_CONCATENATION;
 
 } /* namespace transform */
diff --git a/alib2algo/src/automaton/transform/AutomataConcatenation.h b/alib2algo/src/automaton/transform/AutomataConcatenation.h
index 2cec016f668bc3754b8619223a976ef7e784054a..fb4cdda014b8f27890ba6e296c569e22997e8ca0 100644
--- a/alib2algo/src/automaton/transform/AutomataConcatenation.h
+++ b/alib2algo/src/automaton/transform/AutomataConcatenation.h
@@ -50,6 +50,9 @@ private:
 
 	void Visit(void* data, const automaton::OneTapeDTM& first, const automaton::OneTapeDTM& second) const;
 
+	void Visit(void* data, const automaton::DFTA& first, const automaton::DFTA& second) const;
+	void Visit(void* data, const automaton::NFTA& first, const automaton::NFTA& second) const;
+
 	static const AutomataConcatenation AUTOMATA_CONCATENATION;
 };
 
diff --git a/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.cpp b/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.cpp
index 8dc1219dad761aecc17a50e8432aced706e3cdbe..2c41b90c9879d1f263bccd2867f673e967777e19 100644
--- a/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.cpp
+++ b/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.cpp
@@ -207,6 +207,16 @@ void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::OneTa
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::DFTA&, const automaton::DFTA&) const
+{
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::NFTA&, const automaton::NFTA&) const
+{
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const AutomataConcatenationEpsilonTransition AutomataConcatenationEpsilonTransition::AUTOMATA_CONCATENATION_EPSILON_TRANSITION;
 
 } /* namespace transform */
diff --git a/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h b/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h
index 29ea1403b3b9665a71125c257daa997862b46828..133b493f7a97ade53c498beb1efb217b31b96664 100644
--- a/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h
+++ b/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h
@@ -51,6 +51,9 @@ private:
 
 	void Visit(void* data, const automaton::OneTapeDTM& first, const automaton::OneTapeDTM& second) const;
 
+	void Visit(void* data, const automaton::DFTA& first, const automaton::DFTA& second) const;
+	void Visit(void* data, const automaton::NFTA& first, const automaton::NFTA& second) const;
+
 	static const AutomataConcatenationEpsilonTransition AUTOMATA_CONCATENATION_EPSILON_TRANSITION;
 };
 
diff --git a/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.cpp b/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.cpp
index 2100360dc26b3294721a872c3840d33b45bdc91c..187037c30e2ab79eb877e49faf1958b06af724fc 100644
--- a/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.cpp
+++ b/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.cpp
@@ -180,6 +180,16 @@ void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::OneTape
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::DFTA&, const automaton::DFTA&) const
+{
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::NFTA&, const automaton::NFTA&) const
+{
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const AutomataIntersectionCartesianProduct AutomataIntersectionCartesianProduct::AUTOMATA_INTERSECTION_CARTESIAN_PRODUCT;
 
 } /* namespace transform */
diff --git a/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.h b/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.h
index 2878a772f1f006368b3eee78e8ed6a656765fab7..2369fda445bb5cbdf07f0be6790e02aebe5b03cf 100644
--- a/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.h
+++ b/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.h
@@ -50,6 +50,9 @@ private:
 
 	void Visit(void* data, const automaton::OneTapeDTM& first, const automaton::OneTapeDTM& second) const;
 
+	void Visit(void* data, const automaton::DFTA& first, const automaton::DFTA& second) const;
+	void Visit(void* data, const automaton::NFTA& first, const automaton::NFTA& second) const;
+
 	static const AutomataIntersectionCartesianProduct AUTOMATA_INTERSECTION_CARTESIAN_PRODUCT;
 };
 
diff --git a/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.cpp b/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.cpp
index 380da7f87ac4a9142e035e5ec42bb6fb9e1cafbc..94ba56cbc059b638e36530e0c410d2a181ac1f9d 100644
--- a/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.cpp
+++ b/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.cpp
@@ -194,6 +194,16 @@ void AutomataUnionCartesianProduct::Visit(void*, const automaton::OneTapeDTM&, c
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::DFTA&, const automaton::DFTA&) const
+{
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::NFTA&, const automaton::NFTA&) const
+{
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const AutomataUnionCartesianProduct AutomataUnionCartesianProduct::AUTOMATA_UNION_CARTESIAN_PRODUCT;
 
 } /* namespace transform */
diff --git a/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.h b/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.h
index 936de8af9f8357fb2ef3013e916de602cf668673..424f6f39d85c29b6994fd9e73146321b0db3ff1a 100644
--- a/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.h
+++ b/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.h
@@ -50,6 +50,9 @@ private:
 
 	void Visit(void* data, const automaton::OneTapeDTM& first, const automaton::OneTapeDTM& second) const;
 
+	void Visit(void* data, const automaton::DFTA& first, const automaton::DFTA& second) const;
+	void Visit(void* data, const automaton::NFTA& first, const automaton::NFTA& second) const;
+
 	static const AutomataUnionCartesianProduct AUTOMATA_UNION_CARTESIAN_PRODUCT;
 };
 
diff --git a/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.cpp b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.cpp
index 27cef9981330dc1a74792a70c18abd2340429cc6..a5d303b7a7d0a097a53955f1e411b4b1ac1972e6 100644
--- a/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.cpp
+++ b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.cpp
@@ -227,6 +227,16 @@ void AutomataUnionEpsilonTransition::Visit(void*, const automaton::OneTapeDTM&,
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::DFTA&, const automaton::DFTA&) const
+{
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::NFTA&, const automaton::NFTA&) const
+{
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const AutomataUnionEpsilonTransition AutomataUnionEpsilonTransition::AUTOMATA_UNION_EPSILON_TRANSITION;
 
 } /* namespace transform */
diff --git a/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h
index 07a987af1488c0dde2da411a0bf4a3da37a16d66..7a79873aed1bf7987877b4fcc1f758ef4ab5e265 100644
--- a/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h
+++ b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h
@@ -51,6 +51,9 @@ private:
 
 	void Visit(void* data, const automaton::OneTapeDTM& first, const automaton::OneTapeDTM& second) const;
 
+	void Visit(void* data, const automaton::DFTA& first, const automaton::DFTA& second) const;
+	void Visit(void* data, const automaton::NFTA& first, const automaton::NFTA& second) const;
+
 	static const AutomataUnionEpsilonTransition AUTOMATA_UNION_EPSILON_TRANSITION;
 };
 
diff --git a/alib2algo/src/automaton/transform/AutomatonIteration.cpp b/alib2algo/src/automaton/transform/AutomatonIteration.cpp
index e30f54c1ab04a41c412f914dd4aa583d957bd52d..c1dd029dde8c6b9c11c40a3c93f7c6cb697e0335 100644
--- a/alib2algo/src/automaton/transform/AutomatonIteration.cpp
+++ b/alib2algo/src/automaton/transform/AutomatonIteration.cpp
@@ -123,6 +123,16 @@ void AutomatonIteration::Visit(void*, const automaton::OneTapeDTM&) const
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void AutomatonIteration::Visit(void*, const automaton::DFTA&) const
+{
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void AutomatonIteration::Visit(void*, const automaton::NFTA&) const
+{
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const AutomatonIteration AutomatonIteration::AUTOMATON_ITERATION;
 
 } /* namespace transform */
diff --git a/alib2algo/src/automaton/transform/AutomatonIteration.h b/alib2algo/src/automaton/transform/AutomatonIteration.h
index 7df870107e786c76ab199d480e114e0f2d2d4980..1a7646abd8fdb1202a783b54f937f28b9bd6922b 100644
--- a/alib2algo/src/automaton/transform/AutomatonIteration.h
+++ b/alib2algo/src/automaton/transform/AutomatonIteration.h
@@ -50,6 +50,9 @@ private:
 
 	void Visit(void* data, const automaton::OneTapeDTM& automaton) const;
 
+	void Visit(void* data, const automaton::DFTA& first) const;
+	void Visit(void* data, const automaton::NFTA& first) const;
+
 	static const AutomatonIteration AUTOMATON_ITERATION;
 };
 
diff --git a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
index 61eda50e793d9248c2cf1137088a0e4608f9b0db..739a8f57275f28b50081fc6dd8b420ef0ce493e3 100644
--- a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
+++ b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
@@ -123,6 +123,16 @@ void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::OneTapeD
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::DFTA&) const
+{
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::NFTA&) const
+{
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const AutomatonIterationEpsilonTransition AutomatonIterationEpsilonTransition::AUTOMATON_ITERATION_EPSILON_TRANSITION;
 
 } /* namespace transform */
diff --git a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h
index 2181c1d6f3ad907bf7aedffc5efd7b00ccbffd05..80cf82296d5f3c462c96f877fc88f34216e3c15b 100644
--- a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h
+++ b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h
@@ -50,6 +50,9 @@ private:
 
 	void Visit(void* data, const automaton::OneTapeDTM& automaton) const;
 
+	void Visit(void* data, const automaton::DFTA& first) const;
+	void Visit(void* data, const automaton::NFTA& first) const;
+
 	static const AutomatonIterationEpsilonTransition AUTOMATON_ITERATION_EPSILON_TRANSITION;
 };
 
diff --git a/alib2algo/src/tree/generate/RandomTreeFactory.cpp b/alib2algo/src/tree/generate/RandomTreeFactory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2ec371074f6980626359820d4a698cb383131cc5
--- /dev/null
+++ b/alib2algo/src/tree/generate/RandomTreeFactory.cpp
@@ -0,0 +1,238 @@
+/*
+ * RandomTreeFactory.cpp
+ *
+ *  Created on: 18. 3. 2015
+ *	  Author: Stepan Plachy
+ */
+
+#include "RandomTreeFactory.h"
+
+#include <vector>
+#include <map>
+#include <set>
+#include <algorithm>
+#include <cstdlib>
+#include <ctime>
+#include <cmath>
+
+#include <iostream>
+
+namespace tree {
+
+namespace generate {
+
+int c = 0;
+
+
+struct Node {
+	char symbol;
+	int depth;
+	Node * right;
+	Node * child = NULL;
+	int rank = 0;
+
+	Node() : depth(0) {}
+	Node(Node * parent) : depth(parent -> depth + 1) {
+		if (parent -> child == NULL) {
+			parent -> child = this;
+			right = this;
+		} else {
+			right = parent -> child -> right;
+			parent -> child -> right = this;
+		}
+		parent -> rank++;
+	}
+	~Node() {
+		if (child == NULL) return;
+		Node * ch = child;
+		do {
+			Node * tmp = ch -> right;
+			delete ch;
+			ch = tmp;
+		} while (ch != child);
+	}
+
+	void rotateLeftBranch() {
+		if (child != NULL) child -> rotateLeftBranch();
+		if (rank > 1) {
+			int angle = rand() % rank;
+			Node * newChild = child;
+			for (int i = 0; i < angle; i++) {
+				newChild = newChild -> right;
+			}
+			child = newChild;
+		}
+	}
+
+	void generateUnrankedSymbols(const std::vector<char> & alphabet) {
+		symbol = alphabet[rand() % alphabet.size()];
+		Node * nextChild = child;
+		for(int i = 0; i < rank; i++) {
+				nextChild -> generateUnrankedSymbols(alphabet);
+				nextChild = nextChild -> right;
+		}
+	}
+
+	void generateRankedSymbols(const std::map<int, std::vector<char> > rankedAlphabet) {
+		const std::vector<char> & alphabet = rankedAlphabet.at(rank);
+		symbol = alphabet[rand() % alphabet.size()];
+		Node * nextChild = child;
+		for(int i = 0; i < rank; i++) {
+				nextChild -> generateRankedSymbols(rankedAlphabet);
+				nextChild = nextChild -> right;
+		}
+	}
+
+	void fillRanks(std::map<int, std::vector<char> > & rankedAlphabet) {
+		rankedAlphabet[rank];
+		Node * nextChild = child;
+		for(int i = 0; i < rank; i++) {
+				nextChild -> fillRanks(rankedAlphabet);
+				nextChild = nextChild -> right;
+		}
+	}
+
+	UnrankedNode * createUnrankedNode() {
+		std::list<UnrankedNode *> children;
+		Node * nextChild = child;
+		for(int i = 0; i < rank; i++) {
+				children.push_back(nextChild -> createUnrankedNode());
+				nextChild = nextChild -> right;
+		}
+		return new UnrankedNode(alphabet::LabeledSymbol(symbol), children);
+	}
+
+	RankedNode * createRankedNode() {
+		std::vector<RankedNode *> children;
+		Node * nextChild = child;
+		for(int i = 0; i < rank; i++) {
+				children.push_back(nextChild -> createRankedNode());
+				nextChild = nextChild -> right;
+		}
+		return new RankedNode(alphabet::RankedSymbol(symbol, rank), children);
+	}
+
+	void nicePrint(std::ostream & os = std::cout, const std::string & prefix = "", const bool last = true) const {
+		os << prefix;
+
+		std::string nextPrefix(prefix);
+		if (last) {
+			os << "\\-";
+			nextPrefix += "  ";
+		} else {
+			os << "|-";
+			nextPrefix += "| ";
+		}
+		os << symbol << " (" << rank << ")" << std::endl;
+
+		Node * nextChild = child;
+		for (int i = 0; i < rank; i++)
+		{
+			//os << nextPrefix << "|" << std::endl;
+			nextChild -> nicePrint(os, nextPrefix, i == rank-1);
+			nextChild = nextChild -> right;
+		}
+	}
+};
+
+std::vector<char> generateUnrankedAlphabet(int maxAlphabetSize) {
+	std::vector<char> symbols (26);
+	for(int i = 0; i < 26; i++) symbols[i] = i + 'a';
+	random_shuffle(symbols.begin(), symbols.end());
+	return std::vector<char> (symbols.begin(), symbols.begin() + maxAlphabetSize);
+}
+
+void generateRankedAlphabet(std::map<int, std::vector<char> > & rankedAlphabet, int maxAlphabetSize) {
+	int ranksCount = rankedAlphabet.size();
+	std::vector<char> unrankedAlphabet = generateUnrankedAlphabet(maxAlphabetSize > ranksCount ? maxAlphabetSize : ranksCount);
+
+	std::set<int> rankSeparators;
+	rankSeparators.insert(0);
+	rankSeparators.insert(unrankedAlphabet.size());
+	while ((int)rankSeparators.size() != ranksCount + 1 /*&& rankSeparators.size() != maxRank + 2*/) rankSeparators.insert(rand() % unrankedAlphabet.size());
+
+	std::set<int>::iterator it = rankSeparators.begin();
+	for (std::map<int, std::vector<char> >::iterator i = rankedAlphabet.begin(); i != rankedAlphabet.end(); ++i) {
+		std::set<int>::iterator prevIt = it++;
+		i -> second.insert(i -> second.begin(), unrankedAlphabet.begin() + *prevIt, unrankedAlphabet.begin() + *it);
+	}
+}
+
+Node * generateTreeStructure(int depth, int nodesCount, int maxRank = INT_MAX) {
+	if(maxRank != INT_MAX && pow(maxRank, depth + 1) - 1 < nodesCount) throw exception::AlibException("number of nodes is too small");
+	srand(time(NULL));
+	std::vector<Node *> nodes (nodesCount);
+
+	//generate path depth long
+	Node * root = nodes[0] = new Node();
+	for (int i = 1; i <= depth; i++) nodes[i] = new Node(nodes[i-1]);
+	//move final leaf to end
+	nodes[nodesCount-1] = nodes[depth];
+	
+	int availableNodesIndex = depth;
+	int finalNodesIndex = nodesCount - 2;
+	while(finalNodesIndex >= availableNodesIndex) {
+		int randomIndex = rand() % availableNodesIndex;
+		Node * parent = nodes[randomIndex];
+		Node * node = new Node(parent);
+
+		//put node to end if it reached depth limit
+		if (node -> depth < depth) {
+			nodes[availableNodesIndex] = node;
+			availableNodesIndex++;
+		} else {
+			nodes[finalNodesIndex] = node;
+			finalNodesIndex--;
+		}
+
+		//put parent node to end if it reached rank limit
+		if (parent -> rank >= maxRank) {
+			nodes[randomIndex] = nodes[availableNodesIndex-1];
+			nodes[finalNodesIndex] = parent;
+			availableNodesIndex--;
+			finalNodesIndex--;
+		}
+	}
+
+	//move generated path to random branch
+	root -> rotateLeftBranch();
+
+	return root;
+}
+
+UnrankedTree RandomTreeFactory::generateUnrankedTree(int depth, int nodesCount, int maxAlphabetSize, int maxRank) {
+	Node * root = generateTreeStructure(depth, nodesCount, maxRank);
+	std::vector<char> alphabet = generateUnrankedAlphabet(maxAlphabetSize);
+	root -> generateUnrankedSymbols(alphabet);
+
+	std::set<alphabet::LabeledSymbol> treeAlphabet;
+	for (std::vector<char>::iterator it = alphabet.begin(); it != alphabet.end(); ++it) {
+		treeAlphabet.insert(alphabet::LabeledSymbol(*it));
+	}
+	UnrankedTree tree (treeAlphabet, *std::move(root -> createUnrankedNode()));
+	delete root;
+	return tree;
+}
+
+RankedTree RandomTreeFactory::generateRankedTree(int depth, int nodesCount, int maxAlphabetSize, int maxRank) {
+	Node * root = generateTreeStructure(depth, nodesCount, maxRank);
+	std::map<int, std::vector<char> > rankedAlphabet;
+	root -> fillRanks(rankedAlphabet);
+	generateRankedAlphabet(rankedAlphabet, maxAlphabetSize);
+	root -> generateRankedSymbols(rankedAlphabet);
+
+	std::set<alphabet::RankedSymbol> treeRankedAlphabet;
+	for (std::map<int, std::vector<char> >::iterator it = rankedAlphabet.begin(); it != rankedAlphabet.end(); ++it) {
+		std::vector<char> & alphabet = it -> second;
+		for (std::vector<char>::iterator i = alphabet.begin(); i != alphabet.end(); ++i) {
+			treeRankedAlphabet.insert(alphabet::RankedSymbol(*i, it -> first));
+		}
+	}
+	RankedTree tree (treeRankedAlphabet, std::move(*root -> createRankedNode()));
+	delete root;
+	return tree;
+}
+
+} /* namespace generate */
+
+} /* namespace automaton */
diff --git a/alib2algo/src/tree/generate/RandomTreeFactory.h b/alib2algo/src/tree/generate/RandomTreeFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..89112bb39fa833639f5bdf078c2ee5ee3748ced3
--- /dev/null
+++ b/alib2algo/src/tree/generate/RandomTreeFactory.h
@@ -0,0 +1,37 @@
+/*
+ * RandomTreeFactory.h
+ *
+ *  Created on: 18. 3. 2015
+ *	  Author: Stepan Plachy
+ */
+
+#ifndef RANDOM_TREE_FACTORY_H_
+#define RANDOM_TREE_FACTORY_H_
+
+#include <deque>
+#include <set>
+#include <climits>
+
+#include <exception/AlibException.h>
+#include <alphabet/RankedSymbol.h>
+#include <alphabet/LabeledSymbol.h>
+#include <tree/RankedTree/RankedTree.h>
+#include <tree/UnrankedTree/UnrankedTree.h>
+
+namespace tree {
+
+namespace generate {
+
+class RandomTreeFactory {
+public:
+	static tree::RankedTree generateRankedTree(int depth, int nodesCount, int maxAlphabetSize, int maxRank = INT_MAX);
+	static tree::UnrankedTree generateUnrankedTree(int depth, int nodesCount, int maxAlphabetSize, int maxRank = INT_MAX);
+
+private:
+};
+
+} /* namespace generate */
+
+} /* namespace tree */
+
+#endif /* RANDOM_TREE_FACTORY_H_ */
diff --git a/alib2algo/test-src/automaton/determinize/determinizeTest.cpp b/alib2algo/test-src/automaton/determinize/determinizeTest.cpp
index 0dbc7162d7d42cfed436ce6e219d2686985a7571..500099a10cfc639a78adb7b69d0afd5dc1664fd8 100644
--- a/alib2algo/test-src/automaton/determinize/determinizeTest.cpp
+++ b/alib2algo/test-src/automaton/determinize/determinizeTest.cpp
@@ -2,6 +2,7 @@
 #include "determinizeTest.h"
 
 #include <automaton/FSM/NFA.h>
+#include <automaton/TA/NFTA.h>
 #include <automaton/PDA/InputDrivenNPDA.h>
 #include <automaton/PDA/VisiblyPushdownNPDA.h>
 #include <alphabet/BottomOfTheStackSymbol.h>
@@ -104,3 +105,36 @@ void determinizeTest::testDeterminizeVPA() {
   automaton.addInitialState(automaton::State(0));
   automaton.addFinalState(automaton::State(4));
 }
+
+void determinizeTest::testDeterminizeNFTA() {
+  automaton::NFTA automaton;
+
+  const alphabet::RankedSymbol a ('a', 2);
+  const alphabet::RankedSymbol b ('b', 1);
+  const alphabet::RankedSymbol c ('c', 0);
+  const std::set<alphabet::RankedSymbol> alphabet {a, b, c};
+  automaton.setInputSymbols(alphabet);
+
+  automaton.addState(automaton::State(1));
+  automaton.addState(automaton::State(2));
+  automaton.addState(automaton::State(3));
+
+  std::vector<automaton::State> a1States = {automaton::State(1), automaton::State(3)};
+  automaton.addTransition(a, a1States, automaton::State(1));
+  automaton.addTransition(a, a1States, automaton::State(3));
+  std::vector<automaton::State> a2States = {automaton::State(3), automaton::State(3)};
+  automaton.addTransition(a, a2States, automaton::State(2));
+  std::vector<automaton::State> bStates = {automaton::State(2)};
+  automaton.addTransition(b, bStates, automaton::State(1));
+  std::vector<automaton::State> cStates;
+  automaton.addTransition(c, cStates, automaton::State(3));
+
+  automaton.addFinalState(automaton::State(3));
+
+
+  automaton::DFTA determinized = automaton::determinize::Determinize::determinize(automaton);
+
+  CPPUNIT_ASSERT(determinized.getStates().size() == 5);
+  CPPUNIT_ASSERT(determinized.getFinalStates().size() == 3);
+  CPPUNIT_ASSERT(determinized.getTransitions().size() == 15);
+}
diff --git a/alib2algo/test-src/automaton/determinize/determinizeTest.h b/alib2algo/test-src/automaton/determinize/determinizeTest.h
index 1269f9ad95c40d94cadf1129ca8ab0b62d1de74e..8bb94b7742d68b247bf573a1d904b66cacb97f09 100644
--- a/alib2algo/test-src/automaton/determinize/determinizeTest.h
+++ b/alib2algo/test-src/automaton/determinize/determinizeTest.h
@@ -9,6 +9,7 @@ class determinizeTest : public CppUnit::TestFixture
   CPPUNIT_TEST( testDeterminizeNFA );
   CPPUNIT_TEST( testDeterminizeIDPDA );
   CPPUNIT_TEST( testDeterminizeVPA );
+  CPPUNIT_TEST( testDeterminizeNFTA );
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -18,6 +19,7 @@ public:
   void testDeterminizeNFA();
   void testDeterminizeIDPDA();
   void testDeterminizeVPA();
+  void testDeterminizeNFTA();
 };
 
 #endif  // DETERMINIZE_TEST_H_
diff --git a/alib2data/src/XmlApi.cpp b/alib2data/src/XmlApi.cpp
index 0cdd3c7054ec5fd02786276a6304ad246168826e..cb7bbd5f058a8054d886cf944a6f05a29976817e 100644
--- a/alib2data/src/XmlApi.cpp
+++ b/alib2data/src/XmlApi.cpp
@@ -20,6 +20,7 @@ const exception::ExceptionFromXMLParser FromXMLParsers::exceptionParser;
 const alib::ObjectFromXMLParser FromXMLParsers::objectParser;
 const container::ContainerFromXMLParser FromXMLParsers::containerParser;
 const primitive::PrimitiveFromXMLParser FromXMLParsers::primitiveParser;
+const tree::TreeFromXMLParser FromXMLParsers::treeParser;
 
 const label::LabelToXMLComposer ToXMLComposers::labelComposer;
 const alphabet::SymbolToXMLComposer ToXMLComposers::symbolComposer;
@@ -32,6 +33,7 @@ const alib::ObjectToXMLComposer ToXMLComposers::objectComposer;
 const exception::ExceptionToXMLComposer ToXMLComposers::exceptionComposer;
 const container::ContainerToXMLComposer ToXMLComposers::containerComposer;
 const primitive::PrimitiveToXMLComposer ToXMLComposers::primitiveComposer;
+const tree::TreeToXMLComposer ToXMLComposers::treeComposer;
 
 const ToXMLComposers ToXMLComposers::toXMLComposers;
 
@@ -59,6 +61,8 @@ const std::string Names::AUTOMATON_NFA = "NFA";
 const std::string Names::AUTOMATON_DFA = "DFA";
 const std::string Names::AUTOMATON_EXTENDED_NFA = "ExtendedNFA";
 const std::string Names::AUTOMATON_COMPACT_NFA = "CompactNFA";
+const std::string Names::AUTOMATON_DFTA = "DFTA";
+const std::string Names::AUTOMATON_NFTA = "NFTA";
 const std::string Names::AUTOMATON_DPDA = "DPDA";
 const std::string Names::AUTOMATON_SINGLE_POP_DPDA = "SinglePopDPDA";
 const std::string Names::AUTOMATON_INPUT_DRIVEN_DPDA = "InputDrivenDPDA";
@@ -102,6 +106,8 @@ const std::string Names::PRIMITIVE_INTEGER = "Integer";
 const std::string Names::PRIMITIVE_CHARACTER = "Character";
 const std::string Names::PRIMITIVE_UNSIGNED = "Unsigned";
 const std::string Names::PRIMITIVE_BOOL = "Bool";
+const std::string Names::TREE_RANKED_TREE = "RankedTree";
+const std::string Names::TREE_UNRANKED_TREE = "UnrankedTree";
 
 Void xmlApi<Void>::parse(std::deque<sax::Token>& input) {
 	return FromXMLParsers::objectParser.parseVoid(input);
@@ -572,6 +578,30 @@ void xmlApi<automaton::OneTapeDTM>::compose(std::deque<sax::Token>& output, cons
 	ToXMLComposers::automatonComposer.compose(output, data);
 }
 
+automaton::DFTA xmlApi<automaton::DFTA>::parse(std::deque<sax::Token>& input) {
+	return FromXMLParsers::automatonParser.parseDFTA(input);
+}
+
+bool xmlApi<automaton::DFTA>::first(const std::deque<sax::Token>& input) {
+	return sax::FromXMLParserHelper::isToken(input, sax::Token::TokenType::START_ELEMENT, Names::AUTOMATON_DFTA);
+}
+
+void xmlApi<automaton::DFTA>::compose(std::deque<sax::Token>& output, const automaton::DFTA& data) {
+	ToXMLComposers::automatonComposer.compose(output, data);
+}
+
+automaton::NFTA xmlApi<automaton::NFTA>::parse(std::deque<sax::Token>& input) {
+	return FromXMLParsers::automatonParser.parseNFTA(input);
+}
+
+bool xmlApi<automaton::NFTA>::first(const std::deque<sax::Token>& input) {
+	return sax::FromXMLParserHelper::isToken(input, sax::Token::TokenType::START_ELEMENT, Names::AUTOMATON_NFTA);
+}
+
+void xmlApi<automaton::NFTA>::compose(std::deque<sax::Token>& output, const automaton::NFTA& data) {
+	ToXMLComposers::automatonComposer.compose(output, data);
+}
+
 automaton::State xmlApi<automaton::State>::parse(std::deque<sax::Token>& input) {
 	return FromXMLParsers::automatonParser.parseState(input);
 }
@@ -1094,6 +1124,42 @@ void xmlApi<bool>::compose(std::deque<sax::Token>& output, bool data) {
 	ToXMLComposers::primitiveComposer.compose(output, data);
 }
 
+tree::Tree xmlApi<tree::Tree>::parse(std::deque<sax::Token>& input) {
+	return FromXMLParsers::treeParser.parseTree(input);
+}
+
+bool xmlApi<tree::Tree>::first(const std::deque<sax::Token>& input) {
+	return FromXMLParsers::treeParser.first(input);
+}
+
+void xmlApi<tree::Tree>::compose(std::deque<sax::Token>& output, const tree::Tree& data) {
+	ToXMLComposers::treeComposer.compose(output, data);
+}
+
+tree::RankedTree xmlApi<tree::RankedTree>::parse(std::deque<sax::Token>& input) {
+	return FromXMLParsers::treeParser.parseRankedTree(input);
+}
+
+bool xmlApi<tree::RankedTree>::first(const std::deque<sax::Token>& input) {
+	return sax::FromXMLParserHelper::isToken(input, sax::Token::TokenType::START_ELEMENT, Names::TREE_RANKED_TREE);
+}
+
+void xmlApi<tree::RankedTree>::compose(std::deque<sax::Token>& output, const tree::RankedTree& data) {
+	ToXMLComposers::treeComposer.compose(output, data);
+}
+
+tree::UnrankedTree xmlApi<tree::UnrankedTree>::parse(std::deque<sax::Token>& input) {
+	return FromXMLParsers::treeParser.parseUnrankedTree(input);
+}
+
+bool xmlApi<tree::UnrankedTree>::first(const std::deque<sax::Token>& input) {
+	return sax::FromXMLParserHelper::isToken(input, sax::Token::TokenType::START_ELEMENT, Names::TREE_UNRANKED_TREE);
+}
+
+void xmlApi<tree::UnrankedTree>::compose(std::deque<sax::Token>& output, const tree::UnrankedTree& data) {
+	ToXMLComposers::treeComposer.compose(output, data);
+}
+
 void ToXMLComposers::Visit(void* data, const Void& voidObject) const {
 	xmlApi<Void>::compose(*((std::deque<sax::Token>*) data), voidObject);
 }
@@ -1190,6 +1256,14 @@ void ToXMLComposers::Visit(void* data, const automaton::CompactNFA& automaton) c
 	xmlApi<automaton::CompactNFA>::compose(*((std::deque<sax::Token>*) data), automaton);
 }
 
+void ToXMLComposers::Visit(void* data, const automaton::DFTA& automaton) const {
+	xmlApi<automaton::DFTA>::compose(*((std::deque<sax::Token>*) data), automaton);
+}
+
+void ToXMLComposers::Visit(void* data, const automaton::NFTA& automaton) const {
+	xmlApi<automaton::NFTA>::compose(*((std::deque<sax::Token>*) data), automaton);
+}
+
 void ToXMLComposers::Visit(void* data, const automaton::DPDA& automaton) const {
 	xmlApi<automaton::DPDA>::compose(*((std::deque<sax::Token>*) data), automaton);
 }
@@ -1358,4 +1432,12 @@ void ToXMLComposers::Visit(void* data, const primitive::Bool& primitive) const {
 	xmlApi<primitive::Bool>::compose(*((std::deque<sax::Token>*) data), primitive);
 }
 
+void ToXMLComposers::Visit(void* data, const tree::RankedTree& tree) const {
+	xmlApi<tree::RankedTree>::compose(*((std::deque<sax::Token>*) data), tree);
+}
+
+void ToXMLComposers::Visit(void* data, const tree::UnrankedTree& tree) const {
+	xmlApi<tree::UnrankedTree>::compose(*((std::deque<sax::Token>*) data), tree);
+}
+
 } /* namespace alib */
diff --git a/alib2data/src/XmlApi.hpp b/alib2data/src/XmlApi.hpp
index 7afbb7405606fad1e5a0f15beec7145469a491bc..cf32f8ff9ce2701a29ddd20652e5449a90a11585 100644
--- a/alib2data/src/XmlApi.hpp
+++ b/alib2data/src/XmlApi.hpp
@@ -18,6 +18,7 @@
 #include "object/ObjectFromXMLParser.h"
 #include "exception/ExceptionFromXMLParser.h"
 #include "primitive/PrimitiveFromXMLParser.h"
+#include "tree/TreeFromXMLParser.h"
 
 #include "label/LabelToXMLComposer.h"
 #include "alphabet/SymbolToXMLComposer.h"
@@ -29,6 +30,7 @@
 #include "object/ObjectToXMLComposer.h"
 #include "exception/ExceptionToXMLComposer.h"
 #include "primitive/PrimitiveToXMLComposer.h"
+#include "tree/TreeToXMLComposer.h"
 
 #include "object/ObjectBase.h"
 
@@ -60,6 +62,8 @@ public:
 	const static std::string AUTOMATON_DFA;
 	const static std::string AUTOMATON_EXTENDED_NFA;
 	const static std::string AUTOMATON_COMPACT_NFA;
+	const static std::string AUTOMATON_DFTA;
+	const static std::string AUTOMATON_NFTA;
 	const static std::string AUTOMATON_DPDA;
 	const static std::string AUTOMATON_SINGLE_POP_DPDA;
 	const static std::string AUTOMATON_INPUT_DRIVEN_DPDA;
@@ -103,6 +107,8 @@ public:
 	const static std::string PRIMITIVE_CHARACTER;
 	const static std::string PRIMITIVE_UNSIGNED;
 	const static std::string PRIMITIVE_BOOL;
+	const static std::string TREE_RANKED_TREE;
+	const static std::string TREE_UNRANKED_TREE;
 
 };
 
@@ -346,6 +352,20 @@ struct xmlApi<automaton::CompactNFA> {
 	static void compose(std::deque<sax::Token>& output, const automaton::CompactNFA& data);
 };
 
+template<>
+struct xmlApi<automaton::DFTA> {
+	static automaton::DFTA parse(std::deque<sax::Token>& input);
+	static bool first(const std::deque<sax::Token>& input);
+	static void compose(std::deque<sax::Token>& output, const automaton::DFTA& data);
+};
+
+template<>
+struct xmlApi<automaton::NFTA> {
+	static automaton::NFTA parse(std::deque<sax::Token>& input);
+	static bool first(const std::deque<sax::Token>& input);
+	static void compose(std::deque<sax::Token>& output, const automaton::NFTA& data);
+};
+
 template<>
 struct xmlApi<automaton::DPDA> {
 	static automaton::DPDA parse(std::deque<sax::Token>& input);
@@ -729,6 +749,27 @@ struct xmlApi<bool> {
 	static void compose(std::deque<sax::Token>& output, bool data);
 };
 
+template<>
+struct xmlApi<tree::Tree> {
+	static tree::Tree parse(std::deque<sax::Token>& input);
+	static bool first(const std::deque<sax::Token>& input);
+	static void compose(std::deque<sax::Token>& output, const tree::Tree& data);
+};
+
+template<>
+struct xmlApi<tree::RankedTree> {
+	static tree::RankedTree parse(std::deque<sax::Token>& input);
+	static bool first(const std::deque<sax::Token>& input);
+	static void compose(std::deque<sax::Token>& output, const tree::RankedTree& data);
+};
+
+template<>
+struct xmlApi<tree::UnrankedTree> {
+	static tree::UnrankedTree parse(std::deque<sax::Token>& input);
+	static bool first(const std::deque<sax::Token>& input);
+	static void compose(std::deque<sax::Token>& output, const tree::UnrankedTree& data);
+};
+
 } /* namespace alib */
 
 #include "container/ContainerFromXMLParser.hpp"
@@ -761,6 +802,7 @@ public:
 	static const ObjectFromXMLParser objectParser;
 	static const container::ContainerFromXMLParser containerParser;
 	static const primitive::PrimitiveFromXMLParser primitiveParser;
+	static const tree::TreeFromXMLParser treeParser;
 
 };
 
@@ -788,6 +830,8 @@ class ToXMLComposers : public VisitableObjectBase::const_visitor_type {
 	void Visit(void*, const automaton::DFA& automaton) const;
 	void Visit(void*, const automaton::ExtendedNFA& automaton) const;
 	void Visit(void*, const automaton::CompactNFA& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
 	void Visit(void*, const automaton::DPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopDPDA& automaton) const;
 	void Visit(void*, const automaton::InputDrivenDPDA& automaton) const;
@@ -842,6 +886,9 @@ class ToXMLComposers : public VisitableObjectBase::const_visitor_type {
 	void Visit(void*, const primitive::Unsigned& primitive) const;
 	void Visit(void*, const primitive::Bool& primitive) const;
 
+	void Visit(void*, const tree::RankedTree& tree) const;
+	void Visit(void*, const tree::UnrankedTree& tree) const;
+
 public:
 	static const label::LabelToXMLComposer labelComposer;
 	static const alphabet::SymbolToXMLComposer symbolComposer;
@@ -854,6 +901,7 @@ public:
 	static const ObjectToXMLComposer objectComposer;
 	static const container::ContainerToXMLComposer containerComposer;
 	static const primitive::PrimitiveToXMLComposer primitiveComposer;
+	static const tree::TreeToXMLComposer treeComposer;
 
 	static const ToXMLComposers toXMLComposers;
 };
diff --git a/alib2data/src/automaton/AutomatonBase.h b/alib2data/src/automaton/AutomatonBase.h
index e98ef8e7cad1be867ffac516c970b713ed4d9bdc..0a36d3dcd3d2cbca3dbfe4f7b504125e61c19076 100644
--- a/alib2data/src/automaton/AutomatonBase.h
+++ b/alib2data/src/automaton/AutomatonBase.h
@@ -16,7 +16,7 @@ namespace automaton {
 class AutomatonBase;
 
 typedef std::acceptor_base<AutomatonBase,
-			automaton::DFA, automaton::NFA, automaton::MultiInitialStateNFA, automaton::EpsilonNFA, automaton::CompactNFA, automaton::ExtendedNFA, automaton::DPDA, automaton::SinglePopDPDA, automaton::InputDrivenDPDA, automaton::VisiblyPushdownDPDA, automaton::RealTimeHeightDeterministicDPDA, automaton::NPDA, automaton::SinglePopNPDA, automaton::InputDrivenNPDA, automaton::VisiblyPushdownNPDA, automaton::RealTimeHeightDeterministicNPDA, automaton::OneTapeDTM
+			automaton::DFA, automaton::NFA, automaton::MultiInitialStateNFA, automaton::EpsilonNFA, automaton::CompactNFA, automaton::ExtendedNFA, automaton::DFTA, automaton::NFTA, automaton::DPDA, automaton::SinglePopDPDA, automaton::InputDrivenDPDA, automaton::VisiblyPushdownDPDA, automaton::RealTimeHeightDeterministicDPDA, automaton::NPDA, automaton::SinglePopNPDA, automaton::InputDrivenNPDA, automaton::VisiblyPushdownNPDA, automaton::RealTimeHeightDeterministicNPDA, automaton::OneTapeDTM
 	> VisitableAutomatonBase;
 
 /**
@@ -34,6 +34,14 @@ public:
 
 class VisitableConstFSMBase : public VisitableAutomatonBase::const_visitor_type {
 
+	void Visit(void*, const NFTA&) const {
+		throw exception::AlibException("Unsupported automaton type NFTA");
+	}
+
+	void Visit(void*, const DFTA&) const {
+		throw exception::AlibException("Unsupported automaton type DFTA");
+	}
+
 	void Visit(void*, const DPDA&) const {
 		throw exception::AlibException("Unsupported automaton type DPDA");
 	}
@@ -81,6 +89,14 @@ class VisitableConstFSMBase : public VisitableAutomatonBase::const_visitor_type
 
 class VisitableConstPDABase : public VisitableAutomatonBase::const_visitor_type {
 
+	void Visit(void*, const NFTA&) const {
+		throw exception::AlibException("Unsupported automaton type NFTA");
+	}
+
+	void Visit(void*, const DFTA&) const {
+		throw exception::AlibException("Unsupported automaton type DFTA");
+	}
+
 	void Visit(void*, const EpsilonNFA&) const {
 		throw exception::AlibException("Unsupported automaton type EpsilonNFA");
 	}
@@ -113,6 +129,10 @@ class VisitableConstPDABase : public VisitableAutomatonBase::const_visitor_type
 
 class VisitableConstNondeterministicAutomatonBase : public VisitableAutomatonBase::const_visitor_type {
 
+	void Visit(void*, const DFTA&) const {
+		throw exception::AlibException("Unsupported automaton type DFTA");
+	}
+
 	void Visit(void*, const DFA&) const {
 		throw exception::AlibException("Unsupported automaton type DFA");
 	}
@@ -144,6 +164,10 @@ class VisitableConstNondeterministicAutomatonBase : public VisitableAutomatonBas
 
 class VisitableConstDeterministicAutomatonBase : public VisitableAutomatonBase::const_visitor_type {
 
+	void Visit(void*, const NFTA&) const {
+		throw exception::AlibException("Unsupported automaton type NFTA");
+	}
+
 	void Visit(void*, const EpsilonNFA&) const {
 		throw exception::AlibException("Unsupported automaton type EpsilonNFA");
 	}
diff --git a/alib2data/src/automaton/AutomatonFeatures.h b/alib2data/src/automaton/AutomatonFeatures.h
index 9c9bbdd25dbba4f53d2caec450062f88c14a5ae1..c695337eae98efae92a39553023f799c042df075 100644
--- a/alib2data/src/automaton/AutomatonFeatures.h
+++ b/alib2data/src/automaton/AutomatonFeatures.h
@@ -27,7 +27,9 @@ enum class FEATURES {
 	REAL_TIME_HEIGHT_DETERMINISTIC_NPDA,
 	NPDA,
 	SINGLE_POP_NPDA,
-	ONE_TAPE_DTM
+	ONE_TAPE_DTM,
+	DFTA,
+	NFTA
 };
 
 } /* namespace automaton */
diff --git a/alib2data/src/automaton/AutomatonFromXMLParser.cpp b/alib2data/src/automaton/AutomatonFromXMLParser.cpp
index 893d816a4f0dbb8abb74f4ebec11cc866169a1ab..6112d695f1b1a8c1db0df91d4a05c236ac44ab8a 100644
--- a/alib2data/src/automaton/AutomatonFromXMLParser.cpp
+++ b/alib2data/src/automaton/AutomatonFromXMLParser.cpp
@@ -16,7 +16,7 @@
 namespace automaton {
 
 Automaton AutomatonFromXMLParser::parseAutomaton(std::deque<sax::Token> &input) const {
-	return parseAutomaton(input, std::set<FEATURES>({FEATURES::EPSILON_NFA, FEATURES::MULTI_INITIAL_STATE_NFA, FEATURES::NFA, FEATURES::DFA, FEATURES::COMPACT_NFA, FEATURES::EXTENDED_NFA, FEATURES::DPDA, FEATURES::SINGLE_POP_DPDA, FEATURES::INPUT_DRIVEN_DPDA, FEATURES::INPUT_DRIVEN_NPDA, FEATURES::VISIBLY_PUSHDOWN_DPDA, FEATURES::VISIBLY_PUSHDOWN_NPDA, FEATURES::REAL_TIME_HEIGHT_DETERMINISTIC_DPDA,  FEATURES::REAL_TIME_HEIGHT_DETERMINISTIC_NPDA, FEATURES::NPDA, FEATURES::SINGLE_POP_NPDA, FEATURES::ONE_TAPE_DTM}));
+	return parseAutomaton(input, std::set<FEATURES>({FEATURES::EPSILON_NFA, FEATURES::MULTI_INITIAL_STATE_NFA, FEATURES::NFA, FEATURES::DFA, FEATURES::COMPACT_NFA, FEATURES::EXTENDED_NFA, FEATURES::DFTA, FEATURES::NFTA, FEATURES::DPDA, FEATURES::SINGLE_POP_DPDA, FEATURES::INPUT_DRIVEN_DPDA, FEATURES::INPUT_DRIVEN_NPDA, FEATURES::VISIBLY_PUSHDOWN_DPDA, FEATURES::VISIBLY_PUSHDOWN_NPDA, FEATURES::REAL_TIME_HEIGHT_DETERMINISTIC_DPDA,  FEATURES::REAL_TIME_HEIGHT_DETERMINISTIC_NPDA, FEATURES::NPDA, FEATURES::SINGLE_POP_NPDA, FEATURES::ONE_TAPE_DTM}));
 }
 
 Automaton AutomatonFromXMLParser::parseAutomaton(std::deque<sax::Token>& input, const std::set<FEATURES>& features) const {
@@ -71,12 +71,18 @@ Automaton AutomatonFromXMLParser::parseAutomaton(std::deque<sax::Token>& input,
 	} else if(alib::xmlApi<OneTapeDTM>::first(input)) {
 		if(!features.count(FEATURES::ONE_TAPE_DTM)) throw exception::AlibException();
 		return Automaton(parseOneTapeDTM(input));
+	} else if(alib::xmlApi<DFTA>::first(input)) {
+		if(!features.count(FEATURES::DFTA)) throw exception::AlibException();
+		return Automaton(parseDFTA(input));
+	} else if(alib::xmlApi<NFTA>::first(input)) {
+		if(!features.count(FEATURES::NFTA)) throw exception::AlibException();
+		return Automaton(parseNFTA(input));
 	} else
-		throw sax::ParserException(sax::Token("Automaton / EpsilonNFA / NFA / DFA / CompactNFA / ExtendedNFA / DPDA / SinglePopDPDA / InputDrivenDPDA / InputDrivenNPDA / VisiblyPushdownDPDA / VisiblyPushdownNPDA / RealTimeHeightDeterministicDPDA / RealTimeHeightDeterministicNPDA / NPDA / SinglePopNPDA / OneTapeDTM", sax::Token::TokenType::START_ELEMENT), input.front());
+		throw sax::ParserException(sax::Token("Automaton / EpsilonNFA / NFA / DFA / CompactNFA / ExtendedNFA / DFTA / NFTA / DPDA / SinglePopDPDA / InputDrivenDPDA / InputDrivenNPDA / VisiblyPushdownDPDA / VisiblyPushdownNPDA / RealTimeHeightDeterministicDPDA / RealTimeHeightDeterministicNPDA / NPDA / SinglePopNPDA / OneTapeDTM", sax::Token::TokenType::START_ELEMENT), input.front());
 }
 
 bool AutomatonFromXMLParser::first(const std::deque<sax::Token>& input) const {
-	if(alib::xmlApi<EpsilonNFA>::first(input) || alib::xmlApi<NFA>::first(input) || alib::xmlApi<DFA>::first(input) || alib::xmlApi<CompactNFA>::first(input) || alib::xmlApi<ExtendedNFA>::first(input) || alib::xmlApi<DPDA>::first(input) || alib::xmlApi<SinglePopDPDA>::first(input) || alib::xmlApi<InputDrivenDPDA>::first(input) || alib::xmlApi<InputDrivenNPDA>::first(input) || alib::xmlApi<VisiblyPushdownDPDA>::first(input)  || alib::xmlApi<VisiblyPushdownNPDA>::first(input) || alib::xmlApi<RealTimeHeightDeterministicDPDA>::first(input) || alib::xmlApi<RealTimeHeightDeterministicNPDA>::first(input) || alib::xmlApi<NPDA>::first(input) || alib::xmlApi<SinglePopNPDA>::first(input) || alib::xmlApi<OneTapeDTM>::first(input)) {
+	if(alib::xmlApi<EpsilonNFA>::first(input) || alib::xmlApi<NFA>::first(input) || alib::xmlApi<DFA>::first(input) || alib::xmlApi<CompactNFA>::first(input) || alib::xmlApi<ExtendedNFA>::first(input) || alib::xmlApi<DFTA>::first(input) || alib::xmlApi<NFTA>::first(input) || alib::xmlApi<DPDA>::first(input) || alib::xmlApi<SinglePopDPDA>::first(input) || alib::xmlApi<InputDrivenDPDA>::first(input) || alib::xmlApi<InputDrivenNPDA>::first(input) || alib::xmlApi<VisiblyPushdownDPDA>::first(input)  || alib::xmlApi<VisiblyPushdownNPDA>::first(input) || alib::xmlApi<RealTimeHeightDeterministicDPDA>::first(input) || alib::xmlApi<RealTimeHeightDeterministicNPDA>::first(input) || alib::xmlApi<NPDA>::first(input) || alib::xmlApi<SinglePopNPDA>::first(input) || alib::xmlApi<OneTapeDTM>::first(input)) {
 		return true;
 	} else {
 		return false;
@@ -471,6 +477,42 @@ OneTapeDTM AutomatonFromXMLParser::parseOneTapeDTM(std::deque<sax::Token>& input
 	return automaton;
 }
 
+DFTA AutomatonFromXMLParser::parseDFTA(std::deque<sax::Token>& input) const {
+	popToken(input, sax::Token::TokenType::START_ELEMENT, alib::Names::AUTOMATON_DFTA);
+
+	std::set<State> states = parseStates(input);
+	std::set<alphabet::RankedSymbol> inputSymbols = parseRankedInputAlphabet(input);
+	std::set<State> finalStates = parseFinalStates(input);
+
+	DFTA automaton;
+	automaton.setStates(states);
+	automaton.setInputSymbols(inputSymbols);
+	automaton.setFinalStates(finalStates);
+
+	parseTransitions<DFTA>(input, automaton);
+
+	popToken(input, sax::Token::TokenType::END_ELEMENT, alib::Names::AUTOMATON_DFTA);
+	return automaton;
+}
+
+NFTA AutomatonFromXMLParser::parseNFTA(std::deque<sax::Token>& input) const {
+	popToken(input, sax::Token::TokenType::START_ELEMENT, alib::Names::AUTOMATON_NFTA);
+
+	std::set<State> states = parseStates(input);
+	std::set<alphabet::RankedSymbol> inputSymbols = parseRankedInputAlphabet(input);
+	std::set<State> finalStates = parseFinalStates(input);
+
+	NFTA automaton;
+	automaton.setStates(states);
+	automaton.setInputSymbols(inputSymbols);
+	automaton.setFinalStates(finalStates);
+
+	parseTransitions<NFTA>(input, automaton);
+
+	popToken(input, sax::Token::TokenType::END_ELEMENT, alib::Names::AUTOMATON_NFTA);
+	return automaton;
+}
+
 std::set<State> AutomatonFromXMLParser::parseStates(std::deque<sax::Token> &input) const {
 	std::set<State> states;
 	popToken(input, sax::Token::TokenType::START_ELEMENT, "states");
@@ -525,6 +567,16 @@ std::set<alphabet::Symbol> AutomatonFromXMLParser::parseInputAlphabet(std::deque
 	return inputSymbols;
 }
 
+std::set<alphabet::RankedSymbol> AutomatonFromXMLParser::parseRankedInputAlphabet(std::deque<sax::Token> &input) const {
+	std::set<alphabet::RankedSymbol> inputSymbols;
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "rankedInputAlphabet");
+	while (isTokenType(input, sax::Token::TokenType::START_ELEMENT)) {
+		inputSymbols.insert(alib::xmlApi<alphabet::RankedSymbol>::parse(input));
+	}
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "rankedInputAlphabet");
+	return inputSymbols;
+}
+
 State AutomatonFromXMLParser::parseInitialState(std::deque<sax::Token> &input) const {
 	popToken(input, sax::Token::TokenType::START_ELEMENT, "initialState");
 	State state(alib::xmlApi<label::Label>::parse(input));
@@ -897,6 +949,26 @@ void AutomatonFromXMLParser::parseTransition(std::deque<sax::Token>& input, OneT
 	automaton.addTransition(std::move(from), std::move(inputSymbol), std::move(to), std::move(outputSymbol), shift);
 }
 
+void AutomatonFromXMLParser::parseTransition(std::deque<sax::Token>& input, DFTA& automaton) const {
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "transition");
+	alphabet::RankedSymbol inputSymbol = parseTransitionInputRankedSymbol(input);
+	std::vector<State> from = parseTransitionFromMultiple(input);
+	State to = parseTransitionTo(input);
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "transition");
+
+	automaton.addTransition(inputSymbol, from, to);
+}
+
+void AutomatonFromXMLParser::parseTransition(std::deque<sax::Token>& input, NFTA& automaton) const {
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "transition");
+	alphabet::RankedSymbol inputSymbol = parseTransitionInputRankedSymbol(input);
+	std::vector<State> from = parseTransitionFromMultiple(input);
+	State to = parseTransitionTo(input);
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "transition");
+
+	automaton.addTransition(inputSymbol, from, to);
+}
+
 State AutomatonFromXMLParser::parseTransitionTo(std::deque<sax::Token> &input) const {
 	popToken(input, sax::Token::TokenType::START_ELEMENT, "to");
 	State state(alib::xmlApi<label::Label>::parse(input));
@@ -911,6 +983,16 @@ State AutomatonFromXMLParser::parseTransitionFrom(std::deque<sax::Token> &input)
 	return state;
 }
 
+std::vector<State> AutomatonFromXMLParser::parseTransitionFromMultiple(std::deque<sax::Token> &input) const {
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "from");
+	std::vector<State> states;
+	while (isTokenType(input, sax::Token::TokenType::START_ELEMENT)) {
+		states.push_back(State(alib::xmlApi<label::Label>::parse(input)));
+	}
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "from");
+	return states;
+}
+
 Shift AutomatonFromXMLParser::parseTransitionShift(std::deque<sax::Token>& input) const {
 	Shift shift;
 
@@ -971,6 +1053,13 @@ alphabet::Symbol AutomatonFromXMLParser::parseTransitionInputSymbol(std::deque<s
 	return result;
 }
 
+alphabet::RankedSymbol AutomatonFromXMLParser::parseTransitionInputRankedSymbol(std::deque<sax::Token>& input) const {
+	popToken(input, sax::Token::TokenType::START_ELEMENT, "input");
+	alphabet::RankedSymbol result(alib::xmlApi<alphabet::RankedSymbol>::parse(input));
+	popToken(input, sax::Token::TokenType::END_ELEMENT, "input");
+	return result;
+}
+
 alphabet::Symbol AutomatonFromXMLParser::parseTransitionOutputSymbol(std::deque<sax::Token>& input) const {
 	popToken(input, sax::Token::TokenType::START_ELEMENT, "output");
 	alphabet::Symbol result(alib::xmlApi<alphabet::Symbol>::parse(input));
diff --git a/alib2data/src/automaton/AutomatonFromXMLParser.h b/alib2data/src/automaton/AutomatonFromXMLParser.h
index 9e4a3eb64c2ce10e93b1c3894b6258f7b33dd461..21eb262110beb4156e7009768cb02dcb9b24fdbf 100644
--- a/alib2data/src/automaton/AutomatonFromXMLParser.h
+++ b/alib2data/src/automaton/AutomatonFromXMLParser.h
@@ -28,8 +28,10 @@
 #include "PDA/NPDA.h"
 #include "PDA/SinglePopNPDA.h"
 #include "TM/OneTapeDTM.h"
+#include "TA/DFTA.h"
+#include "TA/NFTA.h"
 
-#include <list>
+#include <deque>
 #include <set>
 #include <variant>
 #include "../sax/Token.h"
@@ -44,7 +46,7 @@ struct xmlApi;
 namespace automaton {
 
 /**
- * Parser used to get general FSM or EpsilonNFA, NFA, DFA from XML parsed into list of Tokens.
+ * Parser used to get general FSM or EpsilonNFA, NFA, DFA from XML parsed into deque of Tokens.
  */
 class AutomatonFromXMLParser : public sax::FromXMLParserHelper {
 	std::set<State> parseStates(std::deque<sax::Token> &input) const;
@@ -53,6 +55,7 @@ class AutomatonFromXMLParser : public sax::FromXMLParserHelper {
 	std::set<alphabet::Symbol> parseCallInputAlphabet(std::deque<sax::Token> &input) const;
 	std::set<alphabet::Symbol> parseReturnInputAlphabet(std::deque<sax::Token> &input) const;
 	std::set<alphabet::Symbol> parseLocalInputAlphabet(std::deque<sax::Token> &input) const;
+	std::set<alphabet::RankedSymbol> parseRankedInputAlphabet(std::deque<sax::Token> &input) const;
 	std::set<alphabet::Symbol> parseStackAlphabet(std::deque<sax::Token> &input) const;
 	std::set<alphabet::Symbol> parseInitialStackSymbols(std::deque<sax::Token> &input) const;
 	alphabet::Symbol parseInitialStackSymbol(std::deque<sax::Token> &input) const;
@@ -66,6 +69,7 @@ class AutomatonFromXMLParser : public sax::FromXMLParserHelper {
 	void parseInputToPushdownStoreOperation(std::deque<sax::Token>& input, automaton::InputDrivenNPDA& automaton) const;
 
 	State parseTransitionFrom(std::deque<sax::Token>& input) const;
+	std::vector<State> parseTransitionFromMultiple(std::deque<sax::Token>& input) const;
 	State parseTransitionTo(std::deque<sax::Token>& input) const;
 	Shift parseTransitionShift(std::deque<sax::Token>& input) const;
 	std::vector<alphabet::Symbol> parseTransitionPop(std::deque<sax::Token>& input) const;
@@ -93,8 +97,11 @@ class AutomatonFromXMLParser : public sax::FromXMLParserHelper {
 	void parseTransition(std::deque<sax::Token>& input, NPDA& automaton) const;
 	void parseTransition(std::deque<sax::Token>& input, SinglePopNPDA& automaton) const;
 	void parseTransition(std::deque<sax::Token>& input, OneTapeDTM& automaton) const;
+	void parseTransition(std::deque<sax::Token>& input, DFTA& automaton) const;
+	void parseTransition(std::deque<sax::Token>& input, NFTA& automaton) const;
 
 	alphabet::Symbol parseTransitionInputSymbol(std::deque<sax::Token> &input) const;
+	alphabet::RankedSymbol parseTransitionInputRankedSymbol(std::deque<sax::Token> &input) const;
 	std::variant<string::Epsilon, alphabet::Symbol> parseTransitionInputEpsilonSymbol(std::deque<sax::Token> &input) const;
 	std::variant<string::Epsilon, alphabet::Symbol> parseTransitionInputBlankEpsilonSymbol(std::deque<sax::Token> &input) const;
 	string::LinearString parseTransitionInputString(std::deque<sax::Token> &input) const;
@@ -127,6 +134,8 @@ class AutomatonFromXMLParser : public sax::FromXMLParserHelper {
 	NPDA parseNPDA(std::deque<sax::Token>& input) const;
 	SinglePopNPDA parseSinglePopNPDA(std::deque<sax::Token>& input) const;
 	OneTapeDTM parseOneTapeDTM(std::deque<sax::Token>& input) const;
+	DFTA parseDFTA(std::deque<sax::Token>& input) const;
+	NFTA parseNFTA(std::deque<sax::Token>& input) const;
 
 	template<typename T> friend class alib::xmlApi;
 public:
diff --git a/alib2data/src/automaton/AutomatonToStringComposer.cpp b/alib2data/src/automaton/AutomatonToStringComposer.cpp
index 8362e48db3ec214868f15293d46de2ef015f82c6..2023d4cd6e6cd41c7ef4fef397be8b907a07b634 100644
--- a/alib2data/src/automaton/AutomatonToStringComposer.cpp
+++ b/alib2data/src/automaton/AutomatonToStringComposer.cpp
@@ -261,4 +261,12 @@ void AutomatonToStringComposer::Visit(void*, const OneTapeDTM&) const {
 	throw exception::AlibException();
 }
 
+void AutomatonToStringComposer::Visit(void*, const DFTA&) const {
+	throw exception::AlibException();
+}
+
+void AutomatonToStringComposer::Visit(void*, const NFTA&) const {
+	throw exception::AlibException();
+}
+
 } /* namespace automaton */
diff --git a/alib2data/src/automaton/AutomatonToStringComposer.h b/alib2data/src/automaton/AutomatonToStringComposer.h
index d0b324f8a03246d6b71e5092aaf84ca4ddc2e8ec..cadab745f0275e2fa5b1d8a365cc03972bd05fd0 100644
--- a/alib2data/src/automaton/AutomatonToStringComposer.h
+++ b/alib2data/src/automaton/AutomatonToStringComposer.h
@@ -35,6 +35,8 @@ class AutomatonToStringComposer : public VisitableAutomatonBase::const_visitor_t
 	void Visit(void*, const NPDA& automaton) const;
 	void Visit(void*, const SinglePopNPDA& automaton) const;
 	void Visit(void*, const OneTapeDTM& automaton) const;
+	void Visit(void*, const DFTA& automaton) const;
+	void Visit(void*, const NFTA& automaton) const;
 
 	void composeTransitionsFromState(std::ostream& out, const DFA& automaton, const State& from) const;
 	void composeTransitionsFromState(std::ostream& out, const NFA& automaton, const State& from) const;
diff --git a/alib2data/src/automaton/AutomatonToXMLComposer.cpp b/alib2data/src/automaton/AutomatonToXMLComposer.cpp
index 737682c9d7930ac6a210793d39cb7e6fa01ba785..2030103543c1f452782e70167c49fa3116770ca6 100644
--- a/alib2data/src/automaton/AutomatonToXMLComposer.cpp
+++ b/alib2data/src/automaton/AutomatonToXMLComposer.cpp
@@ -52,6 +52,14 @@ void AutomatonToXMLComposer::composeLocalInputAlphabet(std::deque<sax::Token>& o
 	out.emplace_back("localInputAlphabet", sax::Token::TokenType::END_ELEMENT);
 }
 
+void AutomatonToXMLComposer::composeRankedInputAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::RankedSymbol>& symbols) const {
+	out.emplace_back(sax::Token("rankedInputAlphabet", sax::Token::TokenType::START_ELEMENT));
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<alphabet::RankedSymbol>::compose(out, symbol);
+	}
+	out.emplace_back(sax::Token("rankedInputAlphabet", sax::Token::TokenType::END_ELEMENT));
+}
+
 void AutomatonToXMLComposer::composeInitialStates(std::deque<sax::Token>& out, const std::set<State>& states) const {
 	out.emplace_back("initialStates", sax::Token::TokenType::START_ELEMENT);
 	for (const auto& state : states) {
@@ -515,6 +523,38 @@ void AutomatonToXMLComposer::composeTransitions(std::deque<sax::Token>& out, con
 	out.emplace_back("transitions", sax::Token::TokenType::END_ELEMENT);
 }
 
+void AutomatonToXMLComposer::composeTransitions(std::deque<sax::Token>& out, const DFTA& automaton) const {
+	out.emplace_back(sax::Token("transitions", sax::Token::TokenType::START_ELEMENT));
+	for(const auto& transition : automaton.getTransitions()) {
+		out.emplace_back(sax::Token("transition", sax::Token::TokenType::START_ELEMENT));
+
+		composeTransitionInputSymbol(out, transition.first.first);
+		composeTransitionFrom(out, transition.first.second);
+		composeTransitionTo(out, transition.second);
+
+		out.emplace_back(sax::Token("transition", sax::Token::TokenType::END_ELEMENT));
+	}
+
+	out.emplace_back(sax::Token("transitions", sax::Token::TokenType::END_ELEMENT));
+}
+
+void AutomatonToXMLComposer::composeTransitions(std::deque<sax::Token>& out, const NFTA& automaton) const {
+	out.emplace_back(sax::Token("transitions", sax::Token::TokenType::START_ELEMENT));
+	for(const auto& transition : automaton.getTransitions()) {
+		for(const auto& targetState: transition.second) {
+			out.emplace_back(sax::Token("transition", sax::Token::TokenType::START_ELEMENT));
+
+			composeTransitionInputSymbol(out, transition.first.first);
+			composeTransitionFrom(out, transition.first.second);
+			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));
+}
+
 void AutomatonToXMLComposer::composeTransitionTo(std::deque<sax::Token>& out, const State& state) const {
 	out.emplace_back("to", sax::Token::TokenType::START_ELEMENT);
 	alib::xmlApi<label::Label>::compose(out, state.getName());
@@ -527,6 +567,14 @@ void AutomatonToXMLComposer::composeTransitionFrom(std::deque<sax::Token>& out,
 	out.emplace_back("from", sax::Token::TokenType::END_ELEMENT);
 }
 
+void AutomatonToXMLComposer::composeTransitionFrom(std::deque<sax::Token>& out, const std::vector<State> & states) const {
+	out.emplace_back(sax::Token("from", sax::Token::TokenType::START_ELEMENT));
+	for (const auto& state : states) {
+		alib::xmlApi<label::Label>::compose(out, state.getName());
+	}
+	out.emplace_back(sax::Token("from", sax::Token::TokenType::END_ELEMENT));
+}
+
 void AutomatonToXMLComposer::composeTransitionShift(std::deque<sax::Token>& out, const Shift shift) const {
 	out.emplace_back("shift", sax::Token::TokenType::START_ELEMENT);
 	out.emplace_back(SHIFT_NAMES [shift], sax::Token::TokenType::CHARACTER);
@@ -567,6 +615,12 @@ void AutomatonToXMLComposer::composeTransitionInputSymbol(std::deque<sax::Token>
 	out.emplace_back("input", sax::Token::TokenType::END_ELEMENT);
 }
 
+void AutomatonToXMLComposer::composeTransitionInputSymbol(std::deque<sax::Token>& out, const alphabet::RankedSymbol& symbol) const {
+	out.emplace_back(sax::Token("input", sax::Token::TokenType::START_ELEMENT));
+	alib::xmlApi<alphabet::RankedSymbol>::compose(out, symbol);
+	out.emplace_back(sax::Token("input", sax::Token::TokenType::END_ELEMENT));
+}
+
 void AutomatonToXMLComposer::composeTransitionOutputSymbol(std::deque<sax::Token>& out, const alphabet::Symbol& symbol) const {
 	out.emplace_back("output", sax::Token::TokenType::START_ELEMENT);
 	alib::xmlApi<alphabet::Symbol>::compose(out, symbol);
@@ -847,6 +901,28 @@ void AutomatonToXMLComposer::compose(std::deque<sax::Token>& out, const OneTapeD
 	out.emplace_back(alib::Names::AUTOMATON_ONE_TAPE_DTM, sax::Token::TokenType::END_ELEMENT);
 }
 
+void AutomatonToXMLComposer::compose(std::deque<sax::Token>& out, const DFTA & automaton) const {
+	out.emplace_back(sax::Token(alib::Names::AUTOMATON_DFTA, sax::Token::TokenType::START_ELEMENT));
+
+	composeStates(out, automaton.getStates());
+	composeRankedInputAlphabet(out, automaton.getInputAlphabet());
+	composeFinalStates(out, automaton.getFinalStates());
+	composeTransitions(out, automaton);
+
+	out.emplace_back(sax::Token(alib::Names::AUTOMATON_DFTA, sax::Token::TokenType::END_ELEMENT));
+}
+
+void AutomatonToXMLComposer::compose(std::deque<sax::Token>& out, const NFTA & automaton) const {
+	out.emplace_back(sax::Token(alib::Names::AUTOMATON_NFTA, sax::Token::TokenType::START_ELEMENT));
+
+	composeStates(out, automaton.getStates());
+	composeRankedInputAlphabet(out, automaton.getInputAlphabet());
+	composeFinalStates(out, automaton.getFinalStates());
+	composeTransitions(out, automaton);
+
+	out.emplace_back(sax::Token(alib::Names::AUTOMATON_NFTA, sax::Token::TokenType::END_ELEMENT));
+}
+
 void AutomatonToXMLComposer::compose(std::deque<sax::Token>& out, const State& state) const {
 	alib::xmlApi<label::Label>::compose(out, state.getName());
 }
diff --git a/alib2data/src/automaton/AutomatonToXMLComposer.h b/alib2data/src/automaton/AutomatonToXMLComposer.h
index ab43de162ff544f1abd524a34c257c5354a73f60..03a15f46d27607a591f65731c9eddf214fa046f3 100644
--- a/alib2data/src/automaton/AutomatonToXMLComposer.h
+++ b/alib2data/src/automaton/AutomatonToXMLComposer.h
@@ -26,6 +26,7 @@
 #include "PDA/NPDA.h"
 #include "PDA/SinglePopNPDA.h"
 #include "TM/OneTapeDTM.h"
+#include "TA/NFTA.h"
 #include "../sax/Token.h"
 
 namespace alib {
@@ -46,6 +47,7 @@ class AutomatonToXMLComposer {
 	void composeCallInputAlphabet(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols) const;
 	void composeReturnInputAlphabet(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols) const;
 	void composeLocalInputAlphabet(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols) const;
+	void composeRankedInputAlphabet(std::deque<sax::Token>&, const std::set<alphabet::RankedSymbol>& symbols) const;
 	void composeInitialStates(std::deque<sax::Token>&, const std::set<State>& states) const;
 	void composeInitialState(std::deque<sax::Token>&, const State& state) const;
 	void composeFinalStates(std::deque<sax::Token>&, const std::set<State>& states) const;
@@ -75,15 +77,19 @@ class AutomatonToXMLComposer {
 	void composeTransitions(std::deque<sax::Token>&, const NPDA& automaton) const;
 	void composeTransitions(std::deque<sax::Token>&, const SinglePopNPDA& automaton) const;
 	void composeTransitions(std::deque<sax::Token>&, const OneTapeDTM& automaton) const;
+	void composeTransitions(std::deque<sax::Token>&, const DFTA& automaton) const;
+	void composeTransitions(std::deque<sax::Token>&, const NFTA& automaton) const;
 
 	void composeTransitionTo(std::deque<sax::Token>&, const State& state) const;
 	void composeTransitionFrom(std::deque<sax::Token>&, const State& state) const;
+	void composeTransitionFrom(std::deque<sax::Token>&, const std::vector<State> & states) const;
 	void composeTransitionShift(std::deque<sax::Token>&, const Shift shift) const;
 	void composeTransitionPop(std::deque<sax::Token>&, const std::vector<alphabet::Symbol>& symbols) const;
 	void composeTransitionSinglePop(std::deque<sax::Token>&, const alphabet::Symbol& symbol) const;
 	void composeTransitionPush(std::deque<sax::Token>&, const std::vector<alphabet::Symbol>& symbols) const;
 	void composeTransitionSinglePush(std::deque<sax::Token>&, const alphabet::Symbol& symbol) const;
 	void composeTransitionInputSymbol(std::deque<sax::Token>&, const alphabet::Symbol& symbol) const;
+	void composeTransitionInputSymbol(std::deque<sax::Token>&, const alphabet::RankedSymbol& symbol) const;
 	void composeTransitionInputEpsilonSymbol(std::deque<sax::Token>&, const std::variant<string::Epsilon, alphabet::Symbol>&) const;
 	void composeTransitionOutputSymbol(std::deque<sax::Token>&, const alphabet::Symbol& symbol) const;
 	void composeTransitionOutputEpsilonSymbol(std::deque<sax::Token>&, const std::variant<string::Epsilon, alphabet::Symbol>&) const;
@@ -98,7 +104,7 @@ class AutomatonToXMLComposer {
 	void compose(std::deque<sax::Token>& output, const AutomatonBase& automaton) const;
 
 	void compose(std::deque<sax::Token>& output, const Automaton& automaton) const;
-	
+
 	void compose(std::deque<sax::Token>& output, const DFA& automaton) const;
 	void compose(std::deque<sax::Token>& output, const NFA& automaton) const;
 	void compose(std::deque<sax::Token>& output, const MultiInitialStateNFA& automaton) const;
@@ -116,6 +122,8 @@ class AutomatonToXMLComposer {
 	void compose(std::deque<sax::Token>& output, const NPDA& automaton) const;
 	void compose(std::deque<sax::Token>& output, const SinglePopNPDA& automaton) const;
 	void compose(std::deque<sax::Token>& output, const OneTapeDTM& automaton) const;
+	void compose(std::deque<sax::Token>& output, const DFTA& automaton) const;
+	void compose(std::deque<sax::Token>& output, const NFTA& automaton) const;
 
 	void compose(std::deque<sax::Token>& output, const State& state) const;
 
diff --git a/alib2data/src/automaton/TA/DFTA.cpp b/alib2data/src/automaton/TA/DFTA.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..12be0fa0e0e5ba5fdd7d57677f849480642135d0
--- /dev/null
+++ b/alib2data/src/automaton/TA/DFTA.cpp
@@ -0,0 +1,111 @@
+/*
+ * DFTA.cpp
+ *
+ *  Created on: Apr 14, 2015
+ *      Author: Stepan Plachy
+ */
+
+#include "DFTA.h"
+#include "../AutomatonException.h"
+#include <ostream>
+#include <sstream>
+
+namespace automaton {
+
+DFTA::DFTA() {
+
+}
+
+AutomatonBase* DFTA::clone() const {
+	return new DFTA(*this);
+}
+
+AutomatonBase* DFTA::plunder() && {
+	return new DFTA(std::move(*this));
+}
+
+bool DFTA::removeState(const State& state) {
+	if (finalStates.find(state) != finalStates.end()) {
+		throw AutomatonException("State \"" + (std::string) state.getName() + "\" is final state.");
+	}
+
+	AutomatonException ex ("State \"" + (std::string) state.getName() + "\" is used in transition.");
+	for (std::map<std::pair<alphabet::RankedSymbol, std::vector<State> >, State>::const_iterator t = transitions.begin(); t != transitions.end(); t++) {
+		const std::vector<State> states = t -> first.second;
+		for (std::vector<State>::const_iterator it = states.begin(); it != states.end(); ++it) {
+			if (*it == state) throw ex;
+		}
+		if (t -> second == state) throw ex;
+	}
+
+	return states.erase(state);
+}
+
+bool DFTA::removeInputSymbol(const alphabet::RankedSymbol& symbol) {
+	for (std::map<std::pair<alphabet::RankedSymbol, std::vector<State> >, State>::const_iterator t = transitions.begin(); t != transitions.end(); t++) {
+		if (t -> first.first == symbol)
+			throw AutomatonException("Input symbol \"" + (std::string) symbol + "\" is used.");
+	}
+
+	return inputAlphabet.erase(symbol);
+}
+
+bool DFTA::addTransition(const alphabet::RankedSymbol & symbol, const std::vector<State> & prevStates, const State & next) {
+
+	if ((int) prevStates.size() != symbol.getRank().getData())
+		throw AutomatonException("Number of states doesn't match rank of the symbol");
+
+	if (inputAlphabet.find(symbol) == inputAlphabet.end())
+		throw AutomatonException("Input symbol \"" + (std::string) symbol + "\" doesn't exist.");
+
+	if (states.find(next) == states.end())
+		throw AutomatonException("State \"" + (std::string) next.getName() + "\" doesn't exist.");
+
+	for (std::vector<State>::const_iterator it = prevStates.begin(); it != prevStates.end(); ++it) {
+		if (states.find(*it) == states.end())
+			throw AutomatonException("State \"" + (std::string) it -> getName() + "\" doesn't exist.");
+	}
+
+	std::pair<alphabet::RankedSymbol, std::vector<State> > key = std::make_pair(symbol, prevStates);
+	const auto & it = transitions.find(key);
+	if (it != transitions.end()) {
+		if (it -> second == next) return false;
+		else throw AutomatonException("Transition already exists");
+	}
+
+	transitions.insert(std::make_pair(key, next));
+	return true;
+}
+
+bool DFTA::removeTransition(const alphabet::RankedSymbol symbol, const std::vector<State> & states, const State & next) {
+	std::pair<alphabet::RankedSymbol, std::vector<State> > key = std::make_pair(symbol, states);
+	const auto & it = transitions.find(key);
+	if (it == transitions.end()) return false;
+	if (it -> second != next) throw AutomatonException("Transition does not exist");
+	return transitions.erase(key);
+}
+
+int DFTA::compare(const DFTA& other) const {
+	auto first = std::tie(states, inputAlphabet, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.finalStates, other.transitions);
+
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
+}
+
+void DFTA::operator>>(std::ostream& out) const {
+	out << "(DFTA "
+		<< " states = " << states
+		<< " inputAlphabet = " << inputAlphabet
+		<< " finalStates = " << finalStates
+		<< " transitions = " << transitions
+		<< ")";
+}
+
+DFTA::operator std::string () const {
+	std::stringstream ss;
+	ss << *this;
+	return ss.str();
+}
+
+} /* namespace automaton */
diff --git a/alib2data/src/automaton/TA/DFTA.h b/alib2data/src/automaton/TA/DFTA.h
new file mode 100644
index 0000000000000000000000000000000000000000..aa1a656778ca7c465e66deb0e182bb352c04d52f
--- /dev/null
+++ b/alib2data/src/automaton/TA/DFTA.h
@@ -0,0 +1,103 @@
+/*
+ * DFTA.h
+ *
+ *  Created on: Apr 14, 2015
+ *      Author: Stepan Plachy
+ */
+
+#ifndef DFTA_H_
+#define DFTA_H_
+
+#include <map>
+#include <vector>
+#include "../AutomatonBase.h"
+#include "../common/States.h"
+//#include "../common/InputAlphabet.h"
+#include "../../alphabet/RankedSymbol.h"
+
+namespace automaton {
+
+/**
+ * Represents Finite Tree Automaton.
+ * Can store nondeterministic finite automaton without epsilon transitions.
+ */
+class DFTA : public std::acceptor<DFTA, VisitableAutomatonBase, std::acceptor<DFTA, alib::VisitableObjectBase, AutomatonBase> >, public States {
+protected:
+	std::set<alphabet::RankedSymbol> inputAlphabet;
+	std::map<std::pair<alphabet::RankedSymbol, std::vector<State> >, State > transitions;
+public:
+	explicit DFTA();
+
+	virtual AutomatonBase* clone() const;
+	
+	virtual AutomatonBase* plunder() &&;
+
+	/**
+	 * @copydoc Automaton::removeState(const State&)
+	 */
+	virtual bool removeState(const State& state);
+
+	/**
+	 * @copydoc Automaton::removeInputSymbol(const Symbol&)
+	 */
+	virtual bool removeInputSymbol(const alphabet::RankedSymbol& symbol);
+	
+	/**
+	 * Adds transition defined by parameters to the automaton.
+	 * @param current current symbol in node
+	 * @param children states of children of current node
+	 * @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 alphabet::RankedSymbol & current, const std::vector<State> & children, const State & next);
+
+	/**
+	 * Removes transition from the automaton.
+	 * @throws AutomatonException when transition doesn't exists.
+	 */
+	bool removeTransition(const alphabet::RankedSymbol symbol, const std::vector<State> & states, const State & next);
+
+	/**
+	 * @return automaton transitions
+	 */
+	const std::map<std::pair<alphabet::RankedSymbol, std::vector<State> >, State > & getTransitions() const {return transitions;}
+
+	std::set<State> getTransitionRightSide(const alphabet::RankedSymbol symbol, const std::vector<State> & states);
+
+	unsigned transitionsSize() const;
+
+	const std::set<alphabet::RankedSymbol> & getInputAlphabet() const {return inputAlphabet;}
+
+	void setInputSymbols(const std::set<alphabet::RankedSymbol> & symbols) {inputAlphabet = symbols;}
+
+	void addInputSymbol(const alphabet::RankedSymbol & symbol) {inputAlphabet.insert(symbol);}
+
+	virtual int compare(const ObjectBase& other) const {
+		return -other.compare(*this);
+	}
+
+	virtual int compare(const DFTA& other) const;
+
+	virtual void operator>>(std::ostream& os) const;
+
+	virtual operator std::string() const;
+
+	virtual int selfTypeId() const {
+		return typeId<DFTA>();
+	}
+};
+
+} /* namespace automaton */
+
+namespace std {
+
+template<>
+struct compare<automaton::DFTA> {
+	int operator()(const automaton::DFTA& first, const automaton::DFTA& second) const {
+		return first.compare(second);
+	}
+};
+
+} /* namespace std */
+
+#endif /* DFTA_H_ */
diff --git a/alib2data/src/automaton/TA/NFTA.cpp b/alib2data/src/automaton/TA/NFTA.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cb0919664ab9bcf851617ce0b3dcc125d363e28d
--- /dev/null
+++ b/alib2data/src/automaton/TA/NFTA.cpp
@@ -0,0 +1,128 @@
+/*
+ * NFTA.cpp
+ *
+ *  Created on: Mar 21, 2015
+ *      Author: Stepan Plachy
+ */
+
+#include "NFTA.h"
+#include "../AutomatonException.h"
+#include <ostream>
+#include <sstream>
+
+namespace automaton {
+
+NFTA::NFTA() {
+
+}
+
+NFTA::NFTA(const DFTA& other) {
+	inputAlphabet = other.getInputAlphabet();
+	states = other.getStates();
+	finalStates = 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::removeState(const State& state) {
+	if (finalStates.find(state) != finalStates.end()) {
+		throw AutomatonException("State \"" + (std::string) state.getName() + "\" is final state.");
+	}
+
+	AutomatonException ex ("State \"" + (std::string) state.getName() + "\" is used in transition.");
+	for (std::map<std::pair<alphabet::RankedSymbol, std::vector<State> >, std::set<State> >::const_iterator t = transitions.begin(); t != transitions.end(); t++) {
+		const std::vector<State> states = t -> first.second;
+		for (std::vector<State>::const_iterator it = states.begin(); it != states.end(); ++it) {
+			if (*it == state) throw ex;
+		}
+		if (t -> second.find(state) != t -> second.end()) throw ex;
+	}
+
+	return states.erase(state);
+}
+
+bool NFTA::removeInputSymbol(const alphabet::RankedSymbol& symbol) {
+	for (std::map<std::pair<alphabet::RankedSymbol, std::vector<State> >, std::set<State> >::const_iterator t = transitions.begin(); t != transitions.end(); t++) {
+		if (t -> first.first == symbol)
+			throw AutomatonException("Input symbol \"" + (std::string) symbol + "\" is used.");
+	}
+
+	return inputAlphabet.erase(symbol);
+}
+
+bool NFTA::addTransition(const alphabet::RankedSymbol & symbol, const std::vector<State> & prevStates, const State & next) {
+
+	if ((int) prevStates.size() != symbol.getRank().getData())
+		throw AutomatonException("Number of states doesn't match rank of the symbol");
+
+	if (inputAlphabet.find(symbol) == inputAlphabet.end())
+		throw AutomatonException("Input symbol \"" + (std::string) symbol + "\" doesn't exist.");
+
+	if (states.find(next) == states.end())
+		throw AutomatonException("State \"" + (std::string) next.getName() + "\" doesn't exist.");
+
+	for (std::vector<State>::const_iterator it = prevStates.begin(); it != prevStates.end(); ++it) {
+		if (states.find(*it) == states.end())
+			throw AutomatonException("State \"" + (std::string) it -> getName() + "\" doesn't exist.");
+	}
+
+	std::pair<alphabet::RankedSymbol, std::vector<State> > key = std::make_pair(symbol, prevStates);
+	return transitions[key].insert(next).second;
+}
+
+bool NFTA::removeTransition(const alphabet::RankedSymbol symbol, const std::vector<State> & states, const State & next) {
+	std::pair<alphabet::RankedSymbol, std::vector<State> > key = std::make_pair(symbol, states);
+	return transitions[key].erase(next);
+}
+
+bool NFTA::isDeterministic() const {
+	for (std::map<std::pair<alphabet::RankedSymbol, std::vector<State> >, std::set<State> >::const_iterator t = transitions.begin(); t != transitions.end(); t++) {
+		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(states, inputAlphabet, finalStates, transitions);
+	auto second = std::tie(other.states, other.inputAlphabet, other.finalStates, other.transitions);
+
+	std::compare<decltype(first)> comp;
+	return comp(first, second);
+}
+
+void NFTA::operator>>(std::ostream& out) const {
+	out << "(NFTA "
+		<< " states = " << states
+		<< " inputAlphabet = " << inputAlphabet
+		<< " finalStates = " << finalStates
+		<< " transitions = " << transitions
+		<< ")";
+}
+
+NFTA::operator std::string () const {
+	std::stringstream ss;
+	ss << *this;
+	return ss.str();
+}
+
+} /* namespace automaton */
diff --git a/alib2data/src/automaton/TA/NFTA.h b/alib2data/src/automaton/TA/NFTA.h
new file mode 100644
index 0000000000000000000000000000000000000000..95aa597b88018eb6cecd8b98bab0b0bde48c9e59
--- /dev/null
+++ b/alib2data/src/automaton/TA/NFTA.h
@@ -0,0 +1,115 @@
+/*
+ * NFTA.h
+ *
+ *  Created on: Mar 21, 2015
+ *      Author: Stepan Plachy
+ */
+
+#ifndef NFTA_H_
+#define NFTA_H_
+
+#include <map>
+#include <vector>
+#include "../AutomatonBase.h"
+#include "../common/States.h"
+//#include "../common/InputAlphabet.h"
+#include "../../alphabet/RankedSymbol.h"
+
+#include "DFTA.h"
+
+namespace automaton {
+
+/**
+ * Represents Finite Tree Automaton.
+ * Can store nondeterministic finite tree automaton without epsilon transitions.
+ */
+class NFTA : public std::acceptor<NFTA, VisitableAutomatonBase, std::acceptor<NFTA, alib::VisitableObjectBase, AutomatonBase> >, public States {
+protected:
+	std::set<alphabet::RankedSymbol> inputAlphabet;
+	std::map<std::pair<alphabet::RankedSymbol, std::vector<State> >, std::set<State> > transitions;
+public:
+	explicit NFTA();
+	explicit NFTA(const DFTA& other);
+
+	virtual AutomatonBase* clone() const;
+	
+	virtual AutomatonBase* plunder() &&;
+
+	/**
+	 * @copydoc Automaton::removeState(const State&)
+	 */
+	virtual bool removeState(const State& state);
+
+	/**
+	 * @copydoc Automaton::removeInputSymbol(const Symbol&)
+	 */
+	virtual bool removeInputSymbol(const alphabet::RankedSymbol& symbol);
+	
+	/**
+	 * Adds transition defined by parameters to the automaton.
+	 * @param current current symbol in node
+	 * @param children states of children of current node
+	 * @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 alphabet::RankedSymbol & current, const std::vector<State> & children, const State & next);
+
+	/**
+	 * Removes transition from the automaton.
+	 * @throws AutomatonException when transition doesn't exists.
+	 */
+	bool removeTransition(const alphabet::RankedSymbol symbol, const std::vector<State> & states, const State & next);
+
+	/**
+	 * @return automaton transitions
+	 */
+	const std::map<std::pair<alphabet::RankedSymbol, std::vector<State> >, std::set<State> > & getTransitions() const {return transitions;}
+
+	std::set<State> getTransitionRightSide(const alphabet::RankedSymbol symbol, const std::vector<State> & states);
+
+	/**
+	 * Determines whether NFTA is deterministic.
+	 * FA is deterministic if and only if:
+	 * \li \c is epsilon free. Trivial for this class
+	 * \li \c size of transition function \delta (from state, input symbol) \leq 1
+	 * @return true when automaton is deterministic, false otherwise
+	 */
+	bool isDeterministic() const;
+
+	unsigned transitionsSize() const;
+
+	const std::set<alphabet::RankedSymbol> & getInputAlphabet() const {return inputAlphabet;}
+
+	void setInputSymbols(const std::set<alphabet::RankedSymbol> & symbols) {inputAlphabet = symbols;}
+
+	void addInputSymbol(const alphabet::RankedSymbol & symbol) {inputAlphabet.insert(symbol);}
+
+	virtual int compare(const ObjectBase& other) const {
+		return -other.compare(*this);
+	}
+
+	virtual int compare(const NFTA& other) const;
+
+	virtual void operator>>(std::ostream& os) const;
+
+	virtual operator std::string() const;
+
+	virtual int selfTypeId() const {
+		return typeId<NFTA>();
+	}
+};
+
+} /* namespace automaton */
+
+namespace std {
+
+template<>
+struct compare<automaton::NFTA> {
+	int operator()(const automaton::NFTA& first, const automaton::NFTA& second) const {
+		return first.compare(second);
+	}
+};
+
+} /* namespace std */
+
+#endif /* NFTA_H_ */
diff --git a/alib2data/src/automaton/TA/TreeAutomaton.h b/alib2data/src/automaton/TA/TreeAutomaton.h
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/alib2data/src/automaton/common/State.h b/alib2data/src/automaton/common/State.h
index 078060ce4aaf4645fdf711da644d527d46084f87..c772f68e0c055a868199fac0700a9d4551558e66 100644
--- a/alib2data/src/automaton/common/State.h
+++ b/alib2data/src/automaton/common/State.h
@@ -41,6 +41,8 @@ public:
 	explicit operator std::string () const;
 };
 
+const State FAILSTATE = State("fail");
+
 } /* namespace automaton */
 
 namespace std {
diff --git a/alib2data/src/object/ObjectBase.h b/alib2data/src/object/ObjectBase.h
index 42204a9f233f4e10d5af453b1c32b5ceebe7e080..f89976ee703c1a930edcecf860c03a24d8b6abc2 100644
--- a/alib2data/src/object/ObjectBase.h
+++ b/alib2data/src/object/ObjectBase.h
@@ -43,6 +43,8 @@ class InputDrivenNPDA;
 class VisiblyPushdownNPDA;
 class RealTimeHeightDeterministicNPDA;
 class OneTapeDTM;
+class DFTA;
+class NFTA;
 
 }
 
@@ -133,6 +135,13 @@ class Bool;
 
 }
 
+namespace tree {
+
+class RankedTree;
+class UnrankedTree;
+
+}
+
 namespace alib {
 
 class ObjectBase;
@@ -140,7 +149,7 @@ class ObjectBase;
 typedef std::acceptor_base<ObjectBase,
 			Void,
 			exception::AlibException,
-			automaton::DFA, automaton::NFA, automaton::MultiInitialStateNFA, automaton::EpsilonNFA, automaton::CompactNFA, automaton::ExtendedNFA, automaton::DPDA, automaton::SinglePopDPDA, automaton::InputDrivenDPDA, automaton::VisiblyPushdownDPDA, automaton::RealTimeHeightDeterministicDPDA, automaton::NPDA, automaton::SinglePopNPDA, automaton::InputDrivenNPDA, automaton::VisiblyPushdownNPDA, automaton::RealTimeHeightDeterministicNPDA, automaton::OneTapeDTM,
+			automaton::DFA, automaton::NFA, automaton::MultiInitialStateNFA, automaton::EpsilonNFA, automaton::CompactNFA, automaton::ExtendedNFA, automaton::DFTA, automaton::NFTA, automaton::DPDA, automaton::SinglePopDPDA, automaton::InputDrivenDPDA, automaton::VisiblyPushdownDPDA, automaton::RealTimeHeightDeterministicDPDA, automaton::NPDA, automaton::SinglePopNPDA, automaton::InputDrivenNPDA, automaton::VisiblyPushdownNPDA, automaton::RealTimeHeightDeterministicNPDA, automaton::OneTapeDTM,
 			grammar::LeftLG, grammar::LeftRG, grammar::RightLG, grammar::RightRG, grammar::LG, grammar::CFG, grammar::EpsilonFreeCFG, grammar::CNF, grammar::GNF, grammar::CSG, grammar::NonContractingGrammar, grammar::ContextPreservingUnrestrictedGrammar, grammar::UnrestrictedGrammar,
 			graph::DirectedGraph, graph::UndirectedGraph,
 			label::PrimitiveLabel, label::HexavigesimalLabel, label::ObjectLabel, label::LabelSetLabel, label::LabelPairLabel, label::UniqueLabel,
@@ -148,7 +157,8 @@ typedef std::acceptor_base<ObjectBase,
 			string::Epsilon, string::LinearString, string::CyclicString,
 			alphabet::EndSymbol, alphabet::LabeledSymbol, alphabet::BlankSymbol, alphabet::BottomOfTheStackSymbol, alphabet::RankedSymbol, alphabet::BarSymbol, alphabet::RankedBarSymbol, alphabet::SubtreeWildcardSymbol, alphabet::SymbolPairSymbol, alphabet::SymbolSetSymbol, alphabet::UniqueSymbol, alphabet::StartSymbol,
 			container::ObjectsSet, container::ObjectsVector, container::ObjectsPair, container::ObjectsMap,
-			primitive::String, primitive::Integer, primitive::Character, primitive::Unsigned, primitive::Bool
+			primitive::String, primitive::Integer, primitive::Character, primitive::Unsigned, primitive::Bool,
+			tree::RankedTree, tree::UnrankedTree
 	> VisitableObjectBase;
 
 class ObjectBase :
@@ -156,7 +166,7 @@ class ObjectBase :
 			ObjectBase,
 			Void,
 			exception::AlibException,
-			automaton::DFA, automaton::NFA, automaton::MultiInitialStateNFA, automaton::EpsilonNFA, automaton::CompactNFA, automaton::ExtendedNFA, automaton::DPDA, automaton::SinglePopDPDA, automaton::InputDrivenDPDA, automaton::VisiblyPushdownDPDA, automaton::RealTimeHeightDeterministicDPDA, automaton::NPDA, automaton::SinglePopNPDA, automaton::InputDrivenNPDA, automaton::VisiblyPushdownNPDA, automaton::RealTimeHeightDeterministicNPDA, automaton::OneTapeDTM,
+			automaton::DFA, automaton::NFA, automaton::MultiInitialStateNFA, automaton::EpsilonNFA, automaton::CompactNFA, automaton::ExtendedNFA, automaton::DFTA, automaton::NFTA, automaton::DPDA, automaton::SinglePopDPDA, automaton::InputDrivenDPDA, automaton::VisiblyPushdownDPDA, automaton::RealTimeHeightDeterministicDPDA, automaton::NPDA, automaton::SinglePopNPDA, automaton::InputDrivenNPDA, automaton::VisiblyPushdownNPDA, automaton::RealTimeHeightDeterministicNPDA, automaton::OneTapeDTM,
 			grammar::LeftLG, grammar::LeftRG, grammar::RightLG, grammar::RightRG, grammar::LG, grammar::CFG, grammar::EpsilonFreeCFG, grammar::CNF, grammar::GNF, grammar::CSG, grammar::NonContractingGrammar, grammar::ContextPreservingUnrestrictedGrammar, grammar::UnrestrictedGrammar,
 			graph::DirectedGraph, graph::UndirectedGraph,
 			label::PrimitiveLabel, label::HexavigesimalLabel, label::ObjectLabel, label::LabelSetLabel, label::LabelPairLabel, label::UniqueLabel,
@@ -164,7 +174,8 @@ class ObjectBase :
 			string::Epsilon, string::LinearString, string::CyclicString,
 			alphabet::EndSymbol, alphabet::LabeledSymbol, alphabet::BlankSymbol, alphabet::BottomOfTheStackSymbol, alphabet::RankedSymbol, alphabet::BarSymbol, alphabet::RankedBarSymbol, alphabet::SubtreeWildcardSymbol, alphabet::SymbolPairSymbol, alphabet::SymbolSetSymbol, alphabet::UniqueSymbol, alphabet::StartSymbol,
 			container::ObjectsSet, container::ObjectsVector, container::ObjectsPair, container::ObjectsMap,
-			primitive::String, primitive::Integer, primitive::Character, primitive::Unsigned, primitive::Bool
+			primitive::String, primitive::Integer, primitive::Character, primitive::Unsigned, primitive::Bool,
+			tree::RankedTree, tree::UnrankedTree
 	>, public VisitableObjectBase {
 };
 
diff --git a/alib2data/src/object/ObjectFromXMLParser.cpp b/alib2data/src/object/ObjectFromXMLParser.cpp
index e27b857f221684150bdcfece7285060e66f5941d..e397829b1672ecf4b5ac404a48d3c512a1d7cb58 100644
--- a/alib2data/src/object/ObjectFromXMLParser.cpp
+++ b/alib2data/src/object/ObjectFromXMLParser.cpp
@@ -51,6 +51,10 @@ Object ObjectFromXMLParser::parseObject(std::deque<sax::Token>& input) const {
 		primitive::Primitive primitive = alib::xmlApi<primitive::Primitive>::parse(input);
 		Object res(std::move(primitive.getData()));
 		return res;
+	} else if(alib::FromXMLParsers::treeParser.first(input)) {
+		tree::Tree tree = alib::xmlApi<tree::Tree>::parse(input);
+		Object res(std::move(tree.getData()));
+		return res;
 	} else if(alib::xmlApi<Void>::first(input)) {
 		Object res(std::move(parseVoid(input)));
 		return res;
diff --git a/alib2data/src/tree/RankedTree/RankedNode.cpp b/alib2data/src/tree/RankedTree/RankedNode.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c68fe7dd7cdad415a0405bf33b52c8485e1604d3
--- /dev/null
+++ b/alib2data/src/tree/RankedTree/RankedNode.cpp
@@ -0,0 +1,193 @@
+/*
+ * RankedNode.cpp
+ *
+ *  Created on: Nov 29, 2014
+ *      Author: Stepan Plachy
+ */
+
+#include "RankedNode.h"
+#include "../TreeException.h"
+#include <iostream>
+#include <set>
+
+namespace tree {
+
+RankedNode::RankedNode(const alphabet::RankedSymbol& symbol, const std::vector<RankedNode *> & children) : symbol(symbol), children(children) {
+	if((int) children.size() != symbol.getRank().getData()) throw TreeException("Number of children doesn't match the rank of the symbol");
+	for (std::vector<RankedNode *>::const_iterator it = children.begin(); it != children.end(); ++it) {
+		(*it) -> parent = this;
+	}
+}
+
+RankedNode::RankedNode(const RankedNode & other) : symbol(other.symbol.getLabel(), other.symbol.getRank()){
+	children = std::vector<RankedNode *>();
+	children.reserve(other.children.size());
+	for (std::vector<RankedNode *>::const_iterator it = other.children.begin(); it != other.children.end(); ++it) {
+		RankedNode * child = (*it) -> clone();
+		child -> parent = this;
+		children.push_back(child);
+	}
+}
+
+RankedNode::RankedNode(RankedNode && other) : symbol(std::move(other.symbol.getLabel()), std::move(other.symbol.getRank())){
+	children = std::vector<RankedNode *>();
+	children.reserve(other.children.size());
+	for (std::vector<RankedNode *>::const_iterator it = other.children.begin(); it != other.children.end(); ++it) {
+		RankedNode * child = std::move(**it).plunder();
+		child -> parent = this;
+		children.push_back(child);
+	}
+}
+
+RankedNode * RankedNode::clone() const {
+	return new RankedNode(*this);
+}
+
+RankedNode * RankedNode::plunder() && {
+	return new RankedNode(std::move(*this));
+}
+
+RankedNode::~RankedNode() {
+	for (std::vector<RankedNode *>::iterator it = children.begin(); it != children.end(); ++it)
+	{
+		delete *it;
+	}
+}
+
+RankedNode & RankedNode::operator=(const RankedNode & other) {
+	if (this == &other) return *this;
+	*this = RankedNode(other);
+	return *this;
+}
+
+RankedNode & RankedNode::operator=(RankedNode && other) {
+	std::swap(symbol, other.symbol);
+	std::swap(children, other.children);
+	for (std::vector<RankedNode *>::iterator it = children.begin(); it != children.end(); ++it)
+		(*it) -> attachRankedTree(tree);
+	return *this;
+}
+
+void RankedNode::setSymbol(alphabet::RankedSymbol & symbol) {
+	if (symbol.getRank().getData() != this -> symbol.getRank().getData()) throw TreeException("New ranked symbol has different rank");
+	this -> symbol = symbol;
+	checkValidSymbol();
+}
+
+void RankedNode::attachRankedTree(RankedTree * tree) {
+	if (this -> tree == tree) return;
+	this -> tree = tree;
+	checkValidSymbol();
+	for (std::vector<RankedNode *>::iterator i = children.begin(); i != children.end(); ++i)
+	{
+		(*i) -> attachRankedTree(tree);
+	}
+}
+
+void RankedNode::checkValidSymbol() const {
+	if (tree == NULL) return;
+	const std::set<alphabet::RankedSymbol> & alphabet = tree -> getRankedAlphabet();
+	if (alphabet.find(symbol) == alphabet.end()) throw TreeException("Ranked alphabet doesn't contain symbol in a node");
+}
+
+bool RankedNode::containsSymbol(const alphabet::RankedSymbol & symbol) const {
+	if(this -> symbol == symbol) return true;
+	for (std::vector<RankedNode *>::const_iterator it = children.begin(); it != children.end(); ++it)
+	{
+		if ((*it) -> containsSymbol(symbol)) return true;
+	}
+	return false;
+}
+
+void RankedNode::changeChild(RankedNode * child, RankedNode * other) {
+	for (std::vector<RankedNode *>::iterator it = children.begin(); it != children.end(); ++it)
+	{
+		if (*it == child) {
+			*it = other;
+			return;
+		}
+	}
+}
+
+void RankedNode::switchSubtree(RankedNode * other) {
+	RankedNode * thisParent = parent;
+	RankedNode * otherParent = other -> parent;
+	if (thisParent != NULL) thisParent -> changeChild(this, other);
+	else if (tree != NULL) tree -> root = other;
+	if (otherParent != NULL) otherParent -> changeChild(other, this);
+	else if (other -> tree != NULL) other -> tree -> root = this;
+	parent = otherParent;
+	other -> parent = thisParent;
+	RankedTree * thisTree = tree;
+	RankedTree * otherTree = other -> tree;
+	attachRankedTree(otherTree);
+	other -> attachRankedTree(thisTree);
+}
+
+
+bool RankedNode::operator < (const RankedNode & other) const {
+	return compare(other) == -1;
+}
+
+bool RankedNode::operator == (const RankedNode & other) const {
+	return compare(other) == 0;
+}
+
+bool RankedNode::operator != (const RankedNode & other) const{
+	return !(*this == other);
+}
+
+int RankedNode::compare(const RankedNode & other) const {
+	if (symbol < other.symbol) return -1;
+	else if (symbol == other.symbol) {
+		std::vector<RankedNode *>::const_iterator i = children.begin();
+		std::vector<RankedNode *>::const_iterator j = other.children.begin();
+		while (i != this -> children.end() && j != other.children.end()) {
+			int result = (*i) -> compare(**j);
+			if (result != 0) return result;
+			++i;
+			++j;
+		}
+		if (i == children.end() && j == other.children.end()) return 0;
+		else if (j == other.children.end()) return 1;
+		else return -1;
+	}
+	else return 1;
+}
+
+std::ostream& operator<<(std::ostream& out, const RankedNode& node) {
+	out << "(Ranked node " 
+		<< " symbol = " << node.symbol
+		<< " children = {";
+		for (std::vector<RankedNode *>::const_iterator it = node.children.begin(); it != node.children.end(); ++it) {
+			out << **it;
+		}
+	out	<< "})";
+	return out;
+}
+
+RankedNode::operator std::string () const {
+	return (std::string) symbol;
+}
+
+void RankedNode::nicePrint(std::ostream & os, const std::string & prefix, const bool last) const {
+	os << prefix;
+
+	std::string nextPrefix(prefix);
+	if (last) {
+		os << "\\-";
+		nextPrefix += "  ";
+	} else {
+		os << "|-";
+		nextPrefix += "| ";
+	}
+	os << (std::string) symbol.getLabel() << "(" << symbol.getRank().getData() << ")" << std::endl;
+
+	for (unsigned int i = 0; i < children.size(); i++)
+	{
+		os << nextPrefix << "|" << std::endl;
+		children[i] -> nicePrint(os, nextPrefix, i == children.size()-1);
+	}
+}
+
+} /* namespace tree */
diff --git a/alib2data/src/tree/RankedTree/RankedNode.h b/alib2data/src/tree/RankedTree/RankedNode.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b4c7c102e6e0e5f1e706922acd406999ce5b2e0
--- /dev/null
+++ b/alib2data/src/tree/RankedTree/RankedNode.h
@@ -0,0 +1,84 @@
+/*
+ * RankedNode.h
+ *
+ *  Created on: Nov 29, 2014
+ *      Author: Stepan Plachy
+ */
+
+#ifndef RANKED_NODE_H_
+#define RANKED_NODE_H_
+
+#include <string>
+#include <ostream>
+#include <vector>
+
+#include "../../label/Label.h"
+#include "../../alphabet/RankedSymbol.h"
+#include "RankedTree.h"
+
+namespace tree {
+
+	class RankedTree;
+
+/**
+ * Class representing node in a ranked tree.
+ */
+class RankedNode {
+protected:
+	alphabet::RankedSymbol symbol;
+	RankedNode * parent = NULL;
+	std::vector<RankedNode *> children;
+	RankedTree * tree = NULL;
+
+	void attachRankedTree(RankedTree *);
+	void changeChild(RankedNode * child, RankedNode * other);
+public:
+	explicit RankedNode(const alphabet::RankedSymbol& symbol, const std::vector<RankedNode *> & children);
+	explicit RankedNode(const RankedNode &);
+	explicit RankedNode(RankedNode &&);
+	~RankedNode();
+	RankedNode & operator= (const RankedNode &);
+	RankedNode & operator= (RankedNode &&);
+
+	RankedNode * clone() const;
+	RankedNode * plunder() &&;
+
+	const alphabet::RankedSymbol& getSymbol() const {return symbol;}
+	void setSymbol(alphabet::RankedSymbol&);
+	RankedNode * getParent() const {return parent;}
+	const std::vector<const RankedNode *> & getChildren() const {return *reinterpret_cast<const std::vector<const RankedNode *> *>(&children);}
+	const std::vector<RankedNode *> & getChildren() {return children;}
+	RankedTree * getRankedTree() const {return tree;}
+	bool containsSymbol(const alphabet::RankedSymbol &) const;
+	void checkValidSymbol() const;
+
+	void switchSubtree(RankedNode * other);
+
+	bool operator < (const RankedNode& other) const;
+	bool operator == (const RankedNode& other) const;
+	bool operator != (const RankedNode& other) const;
+	int compare (const RankedNode& other) const;
+
+	friend std::ostream& operator<<(std::ostream&, const RankedNode&);
+
+	operator std::string () const;
+
+	void nicePrint(std::ostream & = std::cout, const std::string & = "", const bool = true) const;
+
+	friend class RankedTree;
+};
+
+} /* namespace tree */
+
+namespace std {
+
+template<>
+struct compare<tree::RankedNode> {
+	int operator()(const tree::RankedNode& first, const tree::RankedNode& second) const {
+		return first.compare(second);
+	}
+};
+
+} /* namespace std */
+
+#endif /* RANKED_NODE_H_ */
diff --git a/alib2data/src/tree/RankedTree/RankedTree.cpp b/alib2data/src/tree/RankedTree/RankedTree.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..69a7e7ffe602b56723c0f0a00c0ed57dc38c9d8e
--- /dev/null
+++ b/alib2data/src/tree/RankedTree/RankedTree.cpp
@@ -0,0 +1,106 @@
+/*
+ * RankedTree.cpp
+ *
+ *  Created on: Nov 29, 2014
+ *      Author: Stepan Plachy
+ */
+
+#include "RankedTree.h"
+#include "../TreeException.h"
+#include <ostream>
+#include <sstream>
+
+namespace tree {
+
+RankedTree::RankedTree(const std::set<alphabet::RankedSymbol> & rankedAlphabet, const RankedNode & root) : rankedAlphabet(rankedAlphabet) {
+	this -> root = new RankedNode(root);
+	this -> root -> attachRankedTree(this);
+}
+
+RankedTree::RankedTree(const std::set<alphabet::RankedSymbol> & rankedAlphabet, const RankedNode && root) : rankedAlphabet(rankedAlphabet) {
+	this -> root = new RankedNode(root);
+	if (this -> root -> tree != NULL) throw TreeException("Root is already in a tree");
+	this -> root -> attachRankedTree(this);
+}
+
+RankedTree::RankedTree(const RankedTree & other) {
+	rankedAlphabet = other.rankedAlphabet;
+	root = other.root -> clone();
+	root -> attachRankedTree(this);
+}
+
+RankedTree::RankedTree(RankedTree && other) {
+	rankedAlphabet = std::move(other.rankedAlphabet);
+	root = std::move(*other.root).plunder();
+	root -> attachRankedTree(this);
+}
+
+RankedTree::~RankedTree() {
+	delete root;
+}
+
+TreeBase* RankedTree::clone() const {
+	return new RankedTree(*this);
+}
+
+TreeBase* RankedTree::plunder() && {
+	return new RankedTree(std::move(*this));
+}
+
+void RankedTree::addRankedSymbol(alphabet::RankedSymbol & symbol) {
+	rankedAlphabet.insert(symbol);
+}
+
+bool RankedTree::removeRankedSymbol(const alphabet::RankedSymbol& symbol) {
+	if (root -> containsSymbol(symbol)) throw TreeException("Symbol \"" + (std::string) symbol + "\" is used.");
+	return rankedAlphabet.erase(symbol);
+}
+
+bool RankedTree::operator==(const ObjectBase& other) const {
+	return other == *this;
+}
+
+bool RankedTree::operator<(const ObjectBase& other) const {
+	return other > *this;
+}
+
+bool RankedTree::operator>(const ObjectBase& other) const {
+	return other < *this;
+}
+
+bool RankedTree::operator==(const RankedTree & other) const {
+	return this -> rankedAlphabet == other.rankedAlphabet && *(this -> root) == *(other.root);
+}
+
+bool RankedTree::operator<(const RankedTree & other) const {
+	if (this -> rankedAlphabet < other.rankedAlphabet) return true;
+	else if (this -> rankedAlphabet == other.rankedAlphabet) return *(this -> root) < *(other.root);
+	else return false;
+}
+
+void RankedTree::operator>>(std::ostream& out) const {
+	out << "(Ranked tree"
+		<< " rankedAlphabet = " << rankedAlphabet
+		<< " root = " << *root
+		<< ")";
+}
+
+int RankedTree::compare(const RankedTree & other) const {
+	if (this -> rankedAlphabet == other.rankedAlphabet) {
+		return this -> root -> compare(*other.root);
+	}
+	else if (this -> rankedAlphabet < other.rankedAlphabet) return -1;
+	else return 1; 
+}
+
+void RankedTree::nicePrint(std::ostream & os) const {
+	root -> nicePrint(os);
+}
+
+RankedTree::operator std::string () const {
+	std::stringstream ss;
+	ss << *this;
+	return ss.str();
+}
+
+} /* namespace tree */
diff --git a/alib2data/src/tree/RankedTree/RankedTree.h b/alib2data/src/tree/RankedTree/RankedTree.h
new file mode 100644
index 0000000000000000000000000000000000000000..14a93b5ff83aeb827aabf94b8cce5d1ae7187dff
--- /dev/null
+++ b/alib2data/src/tree/RankedTree/RankedTree.h
@@ -0,0 +1,81 @@
+/*
+ * RankedTree.h
+ *
+ *  Created on: Nov 29, 2014
+ *      Author: Stepan Plachy
+ */
+
+#ifndef RANKEDTREE_H_
+#define RANKEDTREE_H_
+
+#include <iostream>
+
+#include "../TreeBase.h"
+#include "RankedNode.h"
+#include "../../alphabet/RankedSymbol.h"
+#include <set>
+
+namespace tree {
+
+	class RankedNode;
+
+/**
+ * Represents Ranked Tree.
+ */
+class RankedTree : public std::acceptor<RankedTree, VisitableTreeBase, std::acceptor<RankedTree, alib::VisitableObjectBase, TreeBase> > {
+protected:
+	std::set<alphabet::RankedSymbol> rankedAlphabet;
+	RankedNode * root;
+public:
+	explicit RankedTree(const std::set<alphabet::RankedSymbol> & rankedAlphabet, const RankedNode & root);
+	explicit RankedTree(const std::set<alphabet::RankedSymbol> & rankedAlphabet, const RankedNode && root);
+	RankedTree(const RankedTree &);
+	explicit RankedTree(RankedTree &&);
+
+	~RankedTree();
+
+	virtual TreeBase* clone() const;
+	
+	virtual TreeBase* plunder() &&;
+
+	/**
+	 * @return tree root
+	 */
+	const RankedNode & getRoot() const {return *root;}
+
+	RankedNode & getRoot() {return *root;}
+
+	const std::set<alphabet::RankedSymbol> & getRankedAlphabet() const {return rankedAlphabet;}
+
+	virtual void addRankedSymbol(alphabet::RankedSymbol & symbol);
+	virtual bool removeRankedSymbol(const alphabet::RankedSymbol & symbol);
+	
+	virtual bool operator<(const alib::ObjectBase& other) const;
+	virtual bool operator==(const alib::ObjectBase& other) const;
+	virtual bool operator>(const alib::ObjectBase& other) const;
+
+	virtual bool operator==(const RankedTree& other) const;
+	virtual bool operator<(const RankedTree& other) const;
+	
+	virtual void operator>>(std::ostream& os) const;
+
+	virtual int compare(const ObjectBase& other) const {
+		return -other.compare(*this);
+	}
+
+	virtual int compare(const RankedTree & other) const;
+
+	virtual operator std::string() const;
+
+	virtual int selfTypeId() const {
+		return typeId<RankedTree>();
+	}
+
+	void nicePrint(std::ostream & os = std::cout) const;
+
+	friend class RankedNode;
+};
+
+} /* namespace tree */
+
+#endif /* RANKEDTREE_H_ */
diff --git a/alib2data/src/tree/Tree.cpp b/alib2data/src/tree/Tree.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9eb3b4fbb035fc0361ffbff994c2bdc0dfe9d62f
--- /dev/null
+++ b/alib2data/src/tree/Tree.cpp
@@ -0,0 +1,17 @@
+/*
+ * Tree.cpp
+ *
+ *  Created on: Nov 16, 2014
+ *      Author: Stepan Plachy
+ */
+
+#include "Tree.h"
+//#include "../label/NextLabel.h"
+//#include "../label/Label.h"
+//#include <climits>
+#include "TreeException.h"
+
+namespace tree {
+
+} /* namespace tree */
+
diff --git a/alib2data/src/tree/Tree.h b/alib2data/src/tree/Tree.h
new file mode 100644
index 0000000000000000000000000000000000000000..5a9b9981e51c76338994266c4820cc6adb493c7e
--- /dev/null
+++ b/alib2data/src/tree/Tree.h
@@ -0,0 +1,24 @@
+/*
+ * Tree.h
+ *
+ *  Created on: Nov 16, 2014
+ *      Author: Stepan Plachy
+ */
+
+#ifndef TREE_H_
+#define TREE_H_
+
+#include "TreeBase.h"
+#include "../common/wrapper.hpp"
+
+namespace tree {
+
+/**
+ * Wrapper around tree.
+ */
+typedef alib::wrapper<TreeBase> Tree;
+
+} /* namespace tree */
+
+#endif /* Tree_H_ */
+
diff --git a/alib2data/src/tree/TreeBase.h b/alib2data/src/tree/TreeBase.h
new file mode 100644
index 0000000000000000000000000000000000000000..8de49f03ae8d148dd4e26bb743efea40172e6808
--- /dev/null
+++ b/alib2data/src/tree/TreeBase.h
@@ -0,0 +1,39 @@
+/*
+ * TreeBase.h
+ *
+ *  Created on: Nov 16, 2014
+ *      Author: Stepan Plachy
+ */
+
+#ifndef TREE_BASE_H_
+#define TREE_BASE_H_
+
+#include "../common/base.hpp"
+#include "../object/ObjectBase.h"
+#include "../exception/AlibException.h"
+
+namespace tree {
+
+class TreeBase;
+
+typedef std::acceptor_base<TreeBase,
+			tree::RankedTree, tree::UnrankedTree
+	> VisitableTreeBase;
+
+/**
+ * Abstract base class for all trees.
+ */
+class TreeBase : public alib::ObjectBase, public VisitableTreeBase {
+public:
+	using VisitableTreeBase::Accept;
+	using alib::VisitableObjectBase::Accept;
+
+	virtual TreeBase* clone() const = 0;
+	virtual TreeBase* plunder() && = 0;
+
+};
+
+} /* namespace tree */
+
+#endif /* TREE_BASE_H_ */
+
diff --git a/alib2data/src/tree/TreeException.cpp b/alib2data/src/tree/TreeException.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..865b888792ebba0a60999e3a58fbccf6ebdba258
--- /dev/null
+++ b/alib2data/src/tree/TreeException.cpp
@@ -0,0 +1,23 @@
+/*
+ * TreeException.cpp
+ *
+ *  Created on: Nov 16, 2014
+ *      Author: Stepan Plachy
+ */
+
+#include "TreeException.h"
+
+namespace tree {
+
+TreeException::TreeException() {
+}
+
+TreeException::TreeException(const std::string& cause) :
+		AlibException(cause) {
+}
+
+TreeException::~TreeException() throw () {
+
+}
+
+} /* namespace tree */
diff --git a/alib2data/src/tree/TreeException.h b/alib2data/src/tree/TreeException.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a30f23de7e2692b619d5384b99e1a76ca108599
--- /dev/null
+++ b/alib2data/src/tree/TreeException.h
@@ -0,0 +1,27 @@
+/*
+ * TreeException.h
+ *
+ *  Created on: Nov 16, 2014
+ *      Author: Stepan Plachy
+ */
+
+#ifndef TREE_EXCEPTION_H_
+#define TREE_EXCEPTION_H_
+
+#include "../exception/AlibException.h"
+
+namespace tree {
+
+/**
+ * Exception thrown by an tree, tree parser or tree printer.
+ */
+class TreeException: public exception::AlibException {
+public:
+	TreeException();
+	explicit TreeException(const std::string& cause);
+	virtual ~TreeException() throw ();
+};
+
+} /* namespace tree */
+
+#endif /* TREE_EXCEPTION_H_ */
diff --git a/alib2data/src/tree/TreeFeatures.h b/alib2data/src/tree/TreeFeatures.h
new file mode 100644
index 0000000000000000000000000000000000000000..4947e68e077814eb4e9dac828dc1f762cd01ce9d
--- /dev/null
+++ b/alib2data/src/tree/TreeFeatures.h
@@ -0,0 +1,19 @@
+/*
+ * TreeFeatures.h
+ *
+ *  Created on: Nov 16, 2014
+ *      Author: Stepan Plachy
+ */
+
+#ifndef TREE_FEATURES_H_
+#define TREE_FEATURES_H_
+
+namespace tree {
+
+enum class FEATURES {
+	RANKED_TREE, UNRANKED_TREE
+};
+
+} /* namespace tree */
+
+#endif /* TREE_FEATURES_H_ */
diff --git a/alib2data/src/tree/TreeFromXMLParser.cpp b/alib2data/src/tree/TreeFromXMLParser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6127c058ff9de14e66dfde97ab3393f18069d4a6
--- /dev/null
+++ b/alib2data/src/tree/TreeFromXMLParser.cpp
@@ -0,0 +1,106 @@
+/*
+ * TreeFromXMLParser.cpp
+ *
+ *  Created on: Nov 16, 2014
+ *      Author: Stepan Plachy
+ */
+
+#include "TreeFromXMLParser.h"
+
+#include "../sax/ParserException.h"
+
+#include "../XmlApi.hpp"
+
+namespace tree {
+
+	Tree TreeFromXMLParser::parseTree(std::deque<sax::Token> &input) const {
+		return parseTree(input, std::set<FEATURES>({FEATURES::RANKED_TREE, FEATURES::UNRANKED_TREE}));
+	}
+
+	Tree TreeFromXMLParser::parseTree(std::deque<sax::Token>& input, const std::set<FEATURES>& features) const {
+		if(alib::xmlApi<RankedTree>::first(input)) {
+			if(!features.count(FEATURES::RANKED_TREE)) throw exception::AlibException();
+			return Tree(parseRankedTree(input));
+		} else if(alib::xmlApi<UnrankedTree>::first(input)) {
+			if(!features.count(FEATURES::UNRANKED_TREE)) throw exception::AlibException();
+			return Tree(parseUnrankedTree(input));
+		} else
+			throw sax::ParserException(sax::Token("Tree / RankedTree / UnrankedTree", sax::Token::TokenType::START_ELEMENT), input.front());
+	}
+
+	RankedTree TreeFromXMLParser::parseRankedTree(std::deque<sax::Token>& input) const {
+		popToken(input, sax::Token::TokenType::START_ELEMENT, alib::Names::TREE_RANKED_TREE);
+
+		std::set<alphabet::RankedSymbol> rankedAlphabet = parseRankedAlphabet(input);
+		RankedNode * root = parseRankedNode(input);
+		RankedTree tree(rankedAlphabet, std::move(*root));
+		popToken(input, sax::Token::TokenType::END_ELEMENT, alib::Names::TREE_RANKED_TREE);
+		return tree;
+	}
+
+	UnrankedTree TreeFromXMLParser::parseUnrankedTree(std::deque<sax::Token>& input) const {
+		popToken(input, sax::Token::TokenType::START_ELEMENT, alib::Names::TREE_UNRANKED_TREE);
+
+		std::set<alphabet::LabeledSymbol> alphabet = parseAlphabet(input);
+		UnrankedNode * root = parseUnrankedNode(input);
+		UnrankedTree tree(alphabet, std::move(*root));
+		popToken(input, sax::Token::TokenType::END_ELEMENT, alib::Names::TREE_UNRANKED_TREE);
+		return tree;
+	}
+
+	std::set<alphabet::RankedSymbol> TreeFromXMLParser::parseRankedAlphabet(std::deque<sax::Token> &input) const {
+		std::set<alphabet::RankedSymbol> rankedSymbols;
+		popToken(input, sax::Token::TokenType::START_ELEMENT, "rankedAlphabet");
+		while (isTokenType(input, sax::Token::TokenType::START_ELEMENT)) {
+			rankedSymbols.insert(alib::xmlApi<alphabet::RankedSymbol>::parse(input));
+		}
+		popToken(input, sax::Token::TokenType::END_ELEMENT, "rankedAlphabet");
+		return rankedSymbols;
+	}
+
+	std::set<alphabet::LabeledSymbol> TreeFromXMLParser::parseAlphabet(std::deque<sax::Token> &input) const {
+		std::set<alphabet::LabeledSymbol> symbols;
+		popToken(input, sax::Token::TokenType::START_ELEMENT, "alphabet");
+		while (isTokenType(input, sax::Token::TokenType::START_ELEMENT)) {
+			symbols.insert(alib::xmlApi<alphabet::LabeledSymbol>::parse(input));
+		}
+		popToken(input, sax::Token::TokenType::END_ELEMENT, "alphabet");
+		return symbols;
+	}
+
+	RankedNode * TreeFromXMLParser::parseRankedNode(std::deque<sax::Token> &input) const {
+		popToken(input, sax::Token::TokenType::START_ELEMENT, "rankedNode");
+		alphabet::RankedSymbol symbol = alib::xmlApi<alphabet::RankedSymbol>::parse(input);
+		int rank = symbol.getRank().getData();
+		std::vector<RankedNode *> children;
+		children.reserve(rank);
+		while (isTokenType(input, sax::Token::TokenType::START_ELEMENT)) {
+			children.push_back(parseRankedNode(input));
+		}
+		popToken(input, sax::Token::TokenType::END_ELEMENT, "rankedNode");
+
+		return new RankedNode(symbol, children);
+	}
+
+	UnrankedNode * TreeFromXMLParser::parseUnrankedNode(std::deque<sax::Token> &input) const {
+		popToken(input, sax::Token::TokenType::START_ELEMENT, "unrankedNode");
+		alphabet::LabeledSymbol symbol = alib::xmlApi<alphabet::LabeledSymbol>::parse(input);
+		std::list<UnrankedNode *> children;
+		while (isTokenType(input, sax::Token::TokenType::START_ELEMENT)) {
+			children.push_back(parseUnrankedNode(input));
+		}
+		popToken(input, sax::Token::TokenType::END_ELEMENT, "unrankedNode");
+
+		return new UnrankedNode(symbol, children);
+	}
+
+	bool TreeFromXMLParser::first(const std::deque<sax::Token>& input) const {
+		if (alib::xmlApi<RankedTree>::first(input) || alib::xmlApi<UnrankedTree>::first(input)) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+} /* namespace tree */
+
diff --git a/alib2data/src/tree/TreeFromXMLParser.h b/alib2data/src/tree/TreeFromXMLParser.h
new file mode 100644
index 0000000000000000000000000000000000000000..a2ace647cd16f36f644ed9a621e1a02d6da80fe3
--- /dev/null
+++ b/alib2data/src/tree/TreeFromXMLParser.h
@@ -0,0 +1,55 @@
+/*
+ * TreeFromXMLParser.h
+ *
+ *  Created on: Nov 16, 2014
+ *      Author: Stepan Plachy
+ */
+
+#ifndef TREE_FROM_XML_PARSER_H_
+#define TREE_FROM_XML_PARSER_H_
+
+#include "../sax/FromXMLParserHelper.h"
+#include "Tree.h"
+#include "TreeFeatures.h"
+#include "RankedTree/RankedTree.h"
+#include "UnrankedTree/UnrankedTree.h"
+
+#include <deque>
+#include <set>
+#include <variant>
+#include "../sax/Token.h"
+
+namespace alib {
+
+template<typename T>
+struct xmlApi;
+
+} /* namespace alib */
+
+namespace tree {
+
+/**
+ * Parser used to get tree from XML parsed into list of Tokens.
+ */
+class TreeFromXMLParser : public sax::FromXMLParserHelper {
+
+	RankedNode * parseRankedNode(std::deque<sax::Token> &input) const;
+	UnrankedNode * parseUnrankedNode(std::deque<sax::Token> &input) const;
+	std::set<alphabet::RankedSymbol> parseRankedAlphabet(std::deque<sax::Token> &input) const;
+	std::set<alphabet::LabeledSymbol> parseAlphabet(std::deque<sax::Token> &input) const;
+
+	Tree parseTree(std::deque<sax::Token>& input) const;
+	Tree parseTree(std::deque<sax::Token>& input, const std::set<FEATURES>& features) const;
+
+	RankedTree parseRankedTree(std::deque<sax::Token>& input) const;
+	UnrankedTree parseUnrankedTree(std::deque<sax::Token>& input) const;
+
+	template<typename T> friend class alib::xmlApi;
+public:
+	bool first(const std::deque<sax::Token>& input) const;
+};
+
+} /* namespace tree */
+
+#endif /* TREE_FROM_XML_PARSER_H_ */
+
diff --git a/alib2data/src/tree/TreeToXMLComposer.cpp b/alib2data/src/tree/TreeToXMLComposer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7a33762e44314f99bb2e7bf9dccf3cb5f8b385e7
--- /dev/null
+++ b/alib2data/src/tree/TreeToXMLComposer.cpp
@@ -0,0 +1,77 @@
+/*
+ * TreeToXMLComposer.cpp
+ *
+ *  Created on: Nov 16, 2014
+ *      Author: Stepan Plachy
+ */
+
+#include "TreeToXMLComposer.h"
+
+#include "../XmlApi.hpp"
+
+namespace tree {
+
+void TreeToXMLComposer::composeAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::RankedSymbol>& symbols) const {
+	out.emplace_back(sax::Token("rankedAlphabet", sax::Token::TokenType::START_ELEMENT));
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<alphabet::RankedSymbol>::compose(out, symbol);
+	}
+	out.emplace_back(sax::Token("rankedAlphabet", sax::Token::TokenType::END_ELEMENT));
+}
+
+void TreeToXMLComposer::composeAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::LabeledSymbol>& symbols) const {
+	out.emplace_back(sax::Token("alphabet", sax::Token::TokenType::START_ELEMENT));
+	for (const auto& symbol : symbols) {
+		alib::xmlApi<alphabet::LabeledSymbol>::compose(out, symbol);
+	}
+	out.emplace_back(sax::Token("alphabet", sax::Token::TokenType::END_ELEMENT));
+}
+
+void TreeToXMLComposer::compose(std::deque<sax::Token>& out, const TreeBase& tree) const {
+	tree.Accept((void*) &out, alib::ToXMLComposers::toXMLComposers);
+}
+
+void TreeToXMLComposer::compose(std::deque<sax::Token>& out, const Tree& tree) const {
+	tree.getData().Accept((void*) &out, alib::ToXMLComposers::toXMLComposers);
+}
+
+void TreeToXMLComposer::compose(std::deque<sax::Token>& out, const RankedTree& tree) const {
+	out.emplace_back(sax::Token(alib::Names::TREE_RANKED_TREE, sax::Token::TokenType::START_ELEMENT));
+
+	composeAlphabet(out, tree.getRankedAlphabet());
+	composeNode(out, tree.getRoot());
+
+	out.emplace_back(sax::Token(alib::Names::TREE_RANKED_TREE, sax::Token::TokenType::END_ELEMENT));
+}
+
+void TreeToXMLComposer::compose(std::deque<sax::Token>& out, const UnrankedTree& tree) const {
+	out.emplace_back(sax::Token(alib::Names::TREE_UNRANKED_TREE, sax::Token::TokenType::START_ELEMENT));
+
+	composeAlphabet(out, tree.getAlphabet());
+	composeNode(out, tree.getRoot());
+
+	out.emplace_back(sax::Token(alib::Names::TREE_UNRANKED_TREE, sax::Token::TokenType::END_ELEMENT));
+}
+
+void TreeToXMLComposer::composeNode(std::deque<sax::Token>& out, const RankedNode& node) const {
+	out.emplace_back(sax::Token("rankedNode", sax::Token::TokenType::START_ELEMENT));
+	alib::xmlApi<alphabet::RankedSymbol>::compose(out, node.getSymbol());
+	for(const auto& child : node.getChildren()) {
+		composeNode(out, *child);
+	}
+
+	out.emplace_back(sax::Token("rankedNode", sax::Token::TokenType::END_ELEMENT));
+}
+
+void TreeToXMLComposer::composeNode(std::deque<sax::Token>& out, const UnrankedNode& node) const {
+	out.emplace_back(sax::Token("unrankedNode", sax::Token::TokenType::START_ELEMENT));
+	alib::xmlApi<alphabet::LabeledSymbol>::compose(out, node.getSymbol());
+	for(const auto& child : node.getChildren()) {
+		composeNode(out, *child);
+	}
+
+	out.emplace_back(sax::Token("unrankedNode", sax::Token::TokenType::END_ELEMENT));
+}
+
+} /* namespace automaton */
+
diff --git a/alib2data/src/tree/TreeToXMLComposer.h b/alib2data/src/tree/TreeToXMLComposer.h
new file mode 100644
index 0000000000000000000000000000000000000000..df71f10d5461c8917f46f71fa355e876300a3082
--- /dev/null
+++ b/alib2data/src/tree/TreeToXMLComposer.h
@@ -0,0 +1,59 @@
+/*
+ * TreeToXMLComposer.h
+ *
+ *  Created on: Nov 16, 2014
+ *      Author: Stepan Plachy
+ */
+
+#ifndef TREE_TO_XML_COMPOSER_H_
+#define TREE_TO_XML_COMPOSER_H_
+
+#include <string>
+#include <deque>
+#include "Tree.h"
+#include "RankedTree/RankedTree.h"
+#include "UnrankedTree/UnrankedTree.h"
+#include "../sax/Token.h"
+
+namespace alib {
+
+template<typename T>
+struct xmlApi;
+
+} /* namespace alib */
+
+namespace tree {
+
+/**
+ * This class contains methods to print XML representation of tree to the output stream.
+ */
+class TreeToXMLComposer {
+
+	void composeAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::RankedSymbol>& symbols) const;
+
+	void composeAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::LabeledSymbol>& symbols) const;
+
+	/**
+	 * Prints XML representation of Tree to the output stream.
+	 * @param tree tree to print
+	 * @return list of xml tokens representing the tree
+	 */
+	void compose(std::deque<sax::Token>& out, const TreeBase& tree) const;
+
+	void compose(std::deque<sax::Token>& out, const Tree& tree) const;
+
+	void compose(std::deque<sax::Token>& out, const RankedTree& tree) const;
+
+	void compose(std::deque<sax::Token>& out, const UnrankedTree& tree) const;
+
+	void composeNode(std::deque<sax::Token>& out, const RankedNode& node) const;
+
+	void composeNode(std::deque<sax::Token>& out, const UnrankedNode& node) const;
+
+	template<typename T> friend class alib::xmlApi;
+};
+
+} /* namespace tree */
+
+#endif /* TREE_TO_XML_COMPOSER_H_ */
+
diff --git a/alib2data/src/tree/UnrankedTree/UnrankedNode.cpp b/alib2data/src/tree/UnrankedTree/UnrankedNode.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8ac61818a7202e428a23361256486ef04cb3c5b8
--- /dev/null
+++ b/alib2data/src/tree/UnrankedTree/UnrankedNode.cpp
@@ -0,0 +1,215 @@
+/*
+ * UnrankedNode.cpp
+ *
+ *  Created on: Mar 9, 2015
+ *      Author: Stepan Plachy
+ */
+
+#include "UnrankedNode.h"
+#include "../TreeException.h"
+#include <iostream>
+#include <set>
+
+namespace tree {
+
+UnrankedNode::UnrankedNode(const alphabet::LabeledSymbol& symbol, const std::list<UnrankedNode *> & children) : symbol(symbol), children(children) {
+	for (std::list<UnrankedNode *>::const_iterator it = children.begin(); it != children.end(); ++it) {
+		(*it) -> parent = this;
+	}
+}
+
+UnrankedNode::UnrankedNode(const UnrankedNode & other) : symbol(other.symbol) {
+	children = std::list<UnrankedNode *>();
+	for (std::list<UnrankedNode *>::const_iterator it = other.children.begin(); it != other.children.end(); ++it) {
+		UnrankedNode * child = (*it) -> clone();
+		child -> parent = this;
+		children.push_back(child);
+	}
+}
+
+UnrankedNode::UnrankedNode(UnrankedNode && other) : symbol(std::move(other.symbol)) {
+	children = std::list<UnrankedNode *>();
+	for (std::list<UnrankedNode *>::const_iterator it = other.children.begin(); it != other.children.end(); ++it) {
+		UnrankedNode * child = std::move(**it).plunder();
+		child -> parent = this;
+		children.push_back(child);
+	}
+}
+
+UnrankedNode * UnrankedNode::clone() const {
+	return new UnrankedNode(*this);
+}
+
+UnrankedNode * UnrankedNode::plunder() && {
+	return new UnrankedNode(std::move(*this));
+}
+
+UnrankedNode::~UnrankedNode() {
+	for (std::list<UnrankedNode *>::iterator it = children.begin(); it != children.end(); ++it)
+	{
+		delete *it;
+	}
+}
+
+UnrankedNode & UnrankedNode::operator=(const UnrankedNode & other) {
+	if (this == &other) return *this;
+	*this = UnrankedNode(other);
+	return *this;
+}
+
+UnrankedNode & UnrankedNode::operator=(UnrankedNode && other) {
+	std::swap(symbol, other.symbol);
+	std::swap(children, other.children);
+	for (std::list<UnrankedNode *>::iterator it = children.begin(); it != children.end(); ++it)
+		(*it) -> attachUnrankedTree(tree);
+	return *this;
+}
+
+void UnrankedNode::setSymbol(alphabet::LabeledSymbol & symbol) {
+	this -> symbol = symbol;
+	checkValidSymbol();
+}
+
+void UnrankedNode::attachUnrankedTree(UnrankedTree * tree) {
+	if (this -> tree == tree) return;
+	this -> tree = tree;
+	checkValidSymbol();
+	for (std::list<UnrankedNode *>::iterator i = children.begin(); i != children.end(); ++i)
+	{
+		(*i) -> attachUnrankedTree(tree);
+	}
+}
+
+void UnrankedNode::checkValidSymbol() const {
+	if (tree == NULL) return;
+	const std::set<alphabet::LabeledSymbol> & alphabet = tree -> getAlphabet();
+	if (alphabet.find(symbol) == alphabet.end()) throw TreeException("Alphabet doesn't contain symbol in a node");
+}
+
+bool UnrankedNode::containsSymbol(const alphabet::LabeledSymbol & symbol) const {
+	if(this -> symbol == symbol) return true;
+	for (std::list<UnrankedNode *>::const_iterator it = children.begin(); it != children.end(); ++it)
+	{
+		if ((*it) -> containsSymbol(symbol)) return true;
+	}
+	return false;
+}
+
+UnrankedNode & UnrankedNode::extract() {
+	parent -> children.remove(this);
+	parent = NULL;
+	attachUnrankedTree(NULL);
+	return *this;
+}
+
+void UnrankedNode::pushBackChild(UnrankedNode & child) {
+	child.attachUnrankedTree(tree);
+	children.push_back(&child);
+}
+
+void UnrankedNode::insertSibling(UnrankedNode & sibling) {
+	parent -> insertChild(this, &sibling);
+}
+
+void UnrankedNode::insertChild(UnrankedNode * position, UnrankedNode * child) {
+	for (std::list<UnrankedNode *>::iterator it = children.begin(); it != children.end(); ++it)
+	{
+		if (*it == position) {
+			children.insert(it, child);
+			return;
+		}
+	}
+}
+
+void UnrankedNode::changeChild(UnrankedNode * child, UnrankedNode * other) {
+	for (std::list<UnrankedNode *>::iterator it = children.begin(); it != children.end(); ++it)
+	{
+		if (*it == child) {
+			*it = other;
+			return;
+		}
+	}
+}
+
+void UnrankedNode::switchSubtree(UnrankedNode * other) {
+	UnrankedNode * thisParent = parent;
+	UnrankedNode * otherParent = other -> parent;
+	if (thisParent != NULL) thisParent -> changeChild(this, other);
+	else if (tree != NULL) tree -> root = other;
+	if (otherParent != NULL) otherParent -> changeChild(other, this);
+	else if (other -> tree != NULL) other -> tree -> root = this;
+	parent = otherParent;
+	other -> parent = thisParent;
+	UnrankedTree * thisTree = tree;
+	UnrankedTree * otherTree = other -> tree;
+	attachUnrankedTree(otherTree);
+	other -> attachUnrankedTree(thisTree);
+}
+
+bool UnrankedNode::operator < (const UnrankedNode & other) const {
+	return compare(other) == -1;
+}
+
+bool UnrankedNode::operator == (const UnrankedNode & other) const {
+	return compare(other) == 0;
+}
+
+bool UnrankedNode::operator != (const UnrankedNode & other) const{
+	return !(*this == other);
+}
+
+int UnrankedNode::compare(const UnrankedNode & other) const {
+	if (symbol < other.symbol) return -1;
+	else if (symbol == other.symbol) {
+		std::list<UnrankedNode *>::const_iterator i = children.begin();
+		std::list<UnrankedNode *>::const_iterator j = other.children.begin();
+		while (i != this -> children.end() && j != other.children.end()) {
+			int result = (*i) -> compare(**j);
+			if (result != 0) return result;
+			++i;
+			++j;
+		}
+		if (i == children.end() && j == other.children.end()) return 0;
+		else if (j == other.children.end()) return 1;
+		else return -1;
+	}
+	else return 1;
+}
+
+std::ostream& operator<<(std::ostream& out, const UnrankedNode& node) {
+	out << "(Unranked node " 
+		<< " symbol = " << node.symbol
+		<< " children = {";
+		for (std::list<UnrankedNode *>::const_iterator it = node.children.begin(); it != node.children.end(); ++it) {
+			out << **it;
+		}
+	out	<< "})";
+	return out;
+}
+
+UnrankedNode::operator std::string () const {
+	return (std::string) symbol;
+}
+
+void UnrankedNode::nicePrint(std::ostream & os, const std::string & prefix, const bool last) const {
+	os << prefix;
+
+	std::string nextPrefix(prefix);
+	if (last) {
+		os << "\\-";
+		nextPrefix += "  ";
+	} else {
+		os << "|-";
+		nextPrefix += "| ";
+	}
+	os << (std::string) symbol.getLabel() << std::endl;
+
+	for (std::list<UnrankedNode *>::const_iterator it = children.begin(); it != children.end(); ++it)
+	{
+		os << nextPrefix << "|" << std::endl;
+		(*it) -> nicePrint(os, nextPrefix, (*it) == children.back());
+	}
+
+}
+
+} /* namespace tree */
diff --git a/alib2data/src/tree/UnrankedTree/UnrankedNode.h b/alib2data/src/tree/UnrankedTree/UnrankedNode.h
new file mode 100644
index 0000000000000000000000000000000000000000..e8f7951247ac3d59288cf81810dbb2baba681dcd
--- /dev/null
+++ b/alib2data/src/tree/UnrankedTree/UnrankedNode.h
@@ -0,0 +1,78 @@
+/*
+ * UnrankedNode.h
+ *
+ *  Created on: Mar 9, 2015
+ *      Author: Stepan Plachy
+ */
+
+#ifndef UNRANKED_NODE_H_
+#define UNRANKED_NODE_H_
+
+#include <string>
+#include <iostream>
+#include <list>
+
+#include "../../label/Label.h"
+#include "../../alphabet/LabeledSymbol.h"
+#include "UnrankedTree.h"
+
+namespace tree {
+
+	class UnrankedTree;
+
+/**
+ * Class representing node in an unranked tree.
+ */
+class UnrankedNode {
+private:
+	alphabet::LabeledSymbol symbol;
+	UnrankedNode * parent = NULL;
+	std::list<UnrankedNode *> children;
+	UnrankedTree * tree = NULL;
+
+	void attachUnrankedTree(UnrankedTree *);
+	void changeChild(UnrankedNode * child, UnrankedNode * other);
+	void insertChild(UnrankedNode * position, UnrankedNode * child);
+public:
+	explicit UnrankedNode(const alphabet::LabeledSymbol& symbol, const std::list<UnrankedNode *> & children);
+	explicit UnrankedNode(const UnrankedNode &);
+	explicit UnrankedNode(UnrankedNode &&);
+	~UnrankedNode();
+	UnrankedNode & operator= (const UnrankedNode &);
+	UnrankedNode & operator= (UnrankedNode &&);
+
+	UnrankedNode * clone() const;
+	UnrankedNode * plunder() &&;
+
+
+	const alphabet::LabeledSymbol& getSymbol() const {return symbol;}
+	void setSymbol(alphabet::LabeledSymbol&);
+	UnrankedNode * getParent() const {return parent;}
+	const std::list<const UnrankedNode *> & getChildren() const {return *reinterpret_cast<const std::list<const UnrankedNode *> *>(&children);}
+	const std::list<UnrankedNode *> & getChildren() {return children;}
+	UnrankedTree * getUnrankedTree() const {return tree;}
+	bool containsSymbol(const alphabet::LabeledSymbol &) const;
+	void checkValidSymbol() const;
+
+	UnrankedNode & extract();
+	void pushBackChild(UnrankedNode &);
+	void insertSibling(UnrankedNode &);
+	void switchSubtree(UnrankedNode * other);
+
+	bool operator < (const UnrankedNode& other) const;
+	bool operator == (const UnrankedNode& other) const;
+	bool operator != (const UnrankedNode& other) const;
+	int compare (const UnrankedNode& other) const;
+
+	friend std::ostream& operator<<(std::ostream&, const UnrankedNode&);
+
+	operator std::string () const;
+
+	void nicePrint(std::ostream & = std::cout, const std::string & = "", const bool = true) const;
+
+	friend class UnrankedTree;
+};
+
+} /* namespace tree */
+
+#endif /* UNRANKED_NODE_H_ */
diff --git a/alib2data/src/tree/UnrankedTree/UnrankedTree.cpp b/alib2data/src/tree/UnrankedTree/UnrankedTree.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6bb837b328ab53176991ab343d48097a25ac3610
--- /dev/null
+++ b/alib2data/src/tree/UnrankedTree/UnrankedTree.cpp
@@ -0,0 +1,106 @@
+/*
+ * UnrankedTree.cpp
+ *
+ *  Created on: Mar 9, 2015
+ *      Author: Stepan Plachy
+ */
+
+#include "UnrankedTree.h"
+#include "../TreeException.h"
+#include <ostream>
+#include <sstream>
+
+namespace tree {
+
+UnrankedTree::UnrankedTree(const std::set<alphabet::LabeledSymbol> & alphabet, const UnrankedNode & root) : alphabet(alphabet) {
+	this -> root = new UnrankedNode(root);
+	this -> root -> attachUnrankedTree(this);
+}
+
+UnrankedTree::UnrankedTree(const std::set<alphabet::LabeledSymbol> & alphabet, const UnrankedNode && root) : alphabet(alphabet) {
+	this -> root = new UnrankedNode(root);
+	if (this -> root -> tree != NULL) throw TreeException("Root is already in a tree");
+	this -> root -> attachUnrankedTree(this);
+}
+
+UnrankedTree::UnrankedTree(const UnrankedTree & other) {
+	alphabet = other.alphabet;
+	root = other.root -> clone();
+	root -> attachUnrankedTree(this);
+}
+
+UnrankedTree::UnrankedTree(UnrankedTree && other) {
+	alphabet = std::move(other.alphabet);
+	root = std::move(*other.root).clone();
+	root -> attachUnrankedTree(this);
+}
+
+UnrankedTree::~UnrankedTree() {
+	delete root;
+}
+
+TreeBase* UnrankedTree::clone() const {
+	return new UnrankedTree(*this);
+}
+
+TreeBase* UnrankedTree::plunder() && {
+	return new UnrankedTree(std::move(*this));
+}
+
+void UnrankedTree::addSymbol(alphabet::LabeledSymbol & symbol) {
+	alphabet.insert(symbol);
+}
+
+bool UnrankedTree::removeSymbol(const alphabet::LabeledSymbol& symbol) {
+	if (root -> containsSymbol(symbol)) throw TreeException("Symbol \"" + (std::string) symbol + "\" is used.");
+	return alphabet.erase(symbol);
+}
+
+bool UnrankedTree::operator==(const ObjectBase& other) const {
+	return other == *this;
+}
+
+bool UnrankedTree::operator<(const ObjectBase& other) const {
+	return other > *this;
+}
+
+bool UnrankedTree::operator>(const ObjectBase& other) const {
+	return other < *this;
+}
+
+bool UnrankedTree::operator==(const UnrankedTree & other) const {
+	return this -> alphabet == other.alphabet && *(this -> root) == *(other.root);
+}
+
+bool UnrankedTree::operator<(const UnrankedTree & other) const {
+	if (this -> alphabet < other.alphabet) return true;
+	else if (this -> alphabet == other.alphabet) return *(this -> root) < *(other.root);
+	else return false;
+}
+
+void UnrankedTree::operator>>(std::ostream& out) const {
+	out << "(Unranked tree"
+		<< " alphabet = " << alphabet
+		<< " root = " << *root
+		<< ")";
+}
+
+int UnrankedTree::compare(const UnrankedTree & other) const {
+	if (this -> alphabet == other.alphabet) {
+		return this -> root -> compare(*other.root);
+	}
+	else if (this -> alphabet < other.alphabet) return -1;
+	else return 1; 
+}
+
+void UnrankedTree::nicePrint(std::ostream & os) const {
+	root -> nicePrint(os);
+}
+
+UnrankedTree::operator std::string () const {
+	std::stringstream ss;
+	ss << *this;
+	return ss.str();
+}
+
+} /* namespace tree */
diff --git a/alib2data/src/tree/UnrankedTree/UnrankedTree.h b/alib2data/src/tree/UnrankedTree/UnrankedTree.h
new file mode 100644
index 0000000000000000000000000000000000000000..c4e6392245fb44507160637477c4d594359cc4bf
--- /dev/null
+++ b/alib2data/src/tree/UnrankedTree/UnrankedTree.h
@@ -0,0 +1,79 @@
+/*
+ * UnrankedTree.h
+ *
+ *  Created on: Mar 9, 2015
+ *      Author: Stepan Plachy
+ */
+
+#ifndef UNRANKEDTREE_H_
+#define UNRANKEDTREE_H_
+
+#include "../TreeBase.h"
+#include "UnrankedNode.h"
+#include "../../alphabet/LabeledSymbol.h"
+#include <set>
+
+#include <iostream>
+
+namespace tree {
+
+	class UnrankedNode;
+
+/**
+ * Represents Unranked Tree.
+ */
+class UnrankedTree : public std::acceptor<UnrankedTree, VisitableTreeBase, std::acceptor<UnrankedTree, alib::VisitableObjectBase, TreeBase> > {
+protected:
+	std::set<alphabet::LabeledSymbol> alphabet;
+	UnrankedNode * root;
+public:
+	explicit UnrankedTree(const std::set<alphabet::LabeledSymbol> & alphabet, const UnrankedNode & root);
+	explicit UnrankedTree(const std::set<alphabet::LabeledSymbol> & alphabet, const UnrankedNode && root);
+	UnrankedTree(const UnrankedTree &);
+	explicit UnrankedTree(UnrankedTree &&);
+
+	~UnrankedTree();
+
+	virtual TreeBase* clone() const;
+	
+	virtual TreeBase* plunder() &&;
+
+	/**
+	 * @return tree root
+	 */
+	UnrankedNode & getRoot() const {return *root;}
+
+	const std::set<alphabet::LabeledSymbol> & getAlphabet() const {return alphabet;}
+
+	virtual void addSymbol(alphabet::LabeledSymbol & symbol);
+	virtual bool removeSymbol(const alphabet::LabeledSymbol & symbol);
+	
+	virtual bool operator<(const alib::ObjectBase& other) const;
+	virtual bool operator==(const alib::ObjectBase& other) const;
+	virtual bool operator>(const alib::ObjectBase& other) const;
+
+	virtual bool operator==(const UnrankedTree& other) const;
+	virtual bool operator<(const UnrankedTree& other) const;
+	
+	virtual void operator>>(std::ostream& os) const;
+
+	virtual int compare(const ObjectBase& other) const {
+		return -other.compare(*this);
+	}
+
+	virtual int compare(const UnrankedTree & other) const;
+
+	virtual operator std::string() const;
+
+	virtual int selfTypeId() const {
+		return typeId<UnrankedTree>();
+	}
+
+	void nicePrint(std::ostream & os = std::cout) const;
+	
+	friend class UnrankedNode;
+};
+
+} /* namespace tree */
+
+#endif /* RANKEDTREE_H_ */
diff --git a/alib2data/test-src/automaton/AutomatonTest.cpp b/alib2data/test-src/automaton/AutomatonTest.cpp
index 8b571818cfe0a00baf47069d06c8e4e65d8946cd..76733d8382e24198f443d3a13d33249e9f7fbc3f 100644
--- a/alib2data/test-src/automaton/AutomatonTest.cpp
+++ b/alib2data/test-src/automaton/AutomatonTest.cpp
@@ -1,4 +1,3 @@
-#include <list>
 #include "AutomatonTest.h"
 
 #include "sax/SaxParseInterface.h"
@@ -8,6 +7,7 @@
 #include "automaton/FSM/ExtendedNFA.h"
 #include "automaton/PDA/SinglePopDPDA.h"
 #include "automaton/PDA/DPDA.h"
+#include "automaton/TA/NFTA.h"
 
 #include "automaton/AutomatonException.h"
 
@@ -307,3 +307,85 @@ void AutomatonTest::testRHPDATransitions() {
 	CPPUNIT_ASSERT(!(automaton < automaton));
 	CPPUNIT_ASSERT(automaton == automaton);
 }
+
+void AutomatonTest::testNFTAParser() {
+	alphabet::RankedSymbol a ('a', 2);
+	alphabet::RankedSymbol b ('b', 1);
+	alphabet::RankedSymbol c ('c', 0);
+
+	automaton::State q2 ("q2");
+	automaton::State q1 ("q1");
+	automaton::State q0 ("q0");
+
+	automaton::NFTA automaton;
+
+	automaton.addState(q2);
+	automaton.addState(q1);
+	automaton.addState(q0);
+	automaton.addInputSymbol(a);
+	automaton.addInputSymbol(b);
+	automaton.addInputSymbol(c);
+
+	std::vector<automaton::State> states1 = {q1, q0};
+	automaton.addTransition(a, states1, q2);
+	automaton.addTransition(a, states1, q1);
+	std::vector<automaton::State> states2 = {q0};
+	automaton.addTransition(b, states2, q1);
+	automaton.addTransition(b, states2, q0);
+	std::vector<automaton::State> states3 = {};
+	automaton.addTransition(c, states3, q0);
+
+	automaton.addFinalState(q2);
+
+	CPPUNIT_ASSERT( automaton == automaton );
+	{
+		std::deque<sax::Token> tokens = alib::XmlDataFactory::toTokens(automaton);
+		std::string tmp;
+		sax::SaxComposeInterface::printMemory(tmp, tokens);
+		std::cout << tmp << std::endl;
+
+		std::deque<sax::Token> tokens2;
+		sax::SaxParseInterface::parseMemory(tmp, tokens2);
+		automaton::NFTA automaton2 = alib::XmlDataFactory::fromTokens<automaton::NFTA>(tokens2);
+
+		CPPUNIT_ASSERT( automaton == automaton2 );
+	}
+}
+
+void AutomatonTest::testNFTATransitions() {
+	alphabet::RankedSymbol a ('a', 2);
+	alphabet::RankedSymbol b ('b', 1);
+	alphabet::RankedSymbol c ('c', 0);
+	alphabet::RankedSymbol d ('d', 0);
+
+	automaton::State q2 ("q2");
+	automaton::State q1 ("q1");
+	automaton::State q0 ("q0");
+
+	automaton::NFTA automaton;
+
+	automaton.addState(q2);
+	automaton.addState(q1);
+	automaton.addState(q0);
+	automaton.addInputSymbol(a);
+	automaton.addInputSymbol(b);
+	automaton.addInputSymbol(c);
+
+	std::vector<automaton::State> states1 = {q1, q0};
+	automaton.addTransition(a, states1, q2);
+	automaton.addTransition(a, states1, q1);
+	std::vector<automaton::State> states2 = {q0};
+	automaton.addTransition(b, states2, q1);
+	automaton.addTransition(b, states2, q0);
+	std::vector<automaton::State> states3 = {};
+	automaton.addTransition(c, states3, q0);
+
+	automaton.addFinalState(q2);
+
+	CPPUNIT_ASSERT_THROW(automaton.removeInputSymbol(a), exception::AlibException);
+	CPPUNIT_ASSERT_NO_THROW(automaton.removeInputSymbol(d));
+	CPPUNIT_ASSERT_NO_THROW(automaton.removeTransition(b, states1, q2));
+	CPPUNIT_ASSERT_THROW(automaton.addTransition(b, states1, q1), exception::AlibException);
+	CPPUNIT_ASSERT_THROW(automaton.addTransition(a, states2, q1), exception::AlibException);
+	CPPUNIT_ASSERT_THROW(automaton.addTransition(d, states3, q0), exception::AlibException);
+}
diff --git a/alib2data/test-src/automaton/AutomatonTest.h b/alib2data/test-src/automaton/AutomatonTest.h
index 5bdc5c7eca8a24395813fa89740e2e28e457f541..3330f48136bed7218591c515b42efda5c86366d0 100644
--- a/alib2data/test-src/automaton/AutomatonTest.h
+++ b/alib2data/test-src/automaton/AutomatonTest.h
@@ -13,6 +13,8 @@ class AutomatonTest : public CppUnit::TestFixture
   CPPUNIT_TEST( testExtendedNFAAlphabet );
   CPPUNIT_TEST( testRHPDATransitions );
   CPPUNIT_TEST( testNPDATransitions );
+  CPPUNIT_TEST( testNFTAParser );
+  CPPUNIT_TEST( testNFTATransitions );
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -26,6 +28,8 @@ public:
   void testExtendedNFAAlphabet();
   void testRHPDATransitions();
   void testNPDATransitions();
+  void testNFTAParser();
+  void testNFTATransitions();
 };
 
 #endif  // AUTOMATON_TEST_H_
diff --git a/alib2data/test-src/tree/TreeTest.cpp b/alib2data/test-src/tree/TreeTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..48e86fd7c8b6b74ecb4c1c2735e5c1377d5de5ae
--- /dev/null
+++ b/alib2data/test-src/tree/TreeTest.cpp
@@ -0,0 +1,430 @@
+#include "TreeTest.h"
+
+#include "sax/SaxParseInterface.h"
+#include "sax/SaxComposeInterface.h"
+
+#include "tree/RankedTree/RankedTree.h"
+
+#include "tree/TreeException.h"
+
+#include "factory/XmlDataFactory.hpp"
+
+#include "alphabet/RankedSymbol.h"
+
+
+#define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y))
+
+CPPUNIT_TEST_SUITE_REGISTRATION( TreeTest );
+
+void TreeTest::setUp() {
+}
+
+void TreeTest::tearDown() {
+}
+
+tree::RankedNode * prefixToNode(const std::string & s, int & pos) {
+	char c = s[pos];
+	int r = s[pos+1] - '0';
+	pos += 2;
+	std::vector<tree::RankedNode *> children (r);
+	for (int i = 0; i < r; i++) {
+		children[i] = prefixToNode(s, pos);
+	}
+	return new tree::RankedNode(alphabet::RankedSymbol(c, r), children);
+}
+
+void TreeTest::testRankedTreeParser() {
+/*
+	L=(a(2), b(1), c(0))
+
+	\-1.a(2)
+	  |
+	  |-2.b(1)
+	  | |
+	  | \-3.c(0)
+	  |
+	  \-4.c(0)
+*/
+	const alphabet::RankedSymbol a ('a', 2);
+	const alphabet::RankedSymbol b ('b', 1);
+	const alphabet::RankedSymbol c ('c', 0);
+
+	const std::set<alphabet::RankedSymbol> alphabet {a, b, c};
+
+	std::vector<tree::RankedNode *> children3 (0);
+	tree::RankedNode * node3 = new tree::RankedNode(c, children3);
+	std::vector<tree::RankedNode *> children4 (0);
+	tree::RankedNode * node4 = new tree::RankedNode(c, children4);
+	std::vector<tree::RankedNode *> children2 {node3};
+	tree::RankedNode * node2 = new tree::RankedNode(b, children2);
+	std::vector<tree::RankedNode *> children1 {node2, node4};
+	tree::RankedNode * node1 = new tree::RankedNode(a, children1);
+
+	tree::RankedTree tree(alphabet, std::move(*node1));
+
+	CPPUNIT_ASSERT( tree == tree );
+	tree.getRoot().nicePrint(std::cout);
+	{
+		std::deque<sax::Token> tokens = alib::XmlDataFactory::toTokens(tree);
+		std::string tmp;
+		sax::SaxComposeInterface::printMemory(tmp, tokens);
+
+		std::deque<sax::Token> tokens2;
+		sax::SaxParseInterface::parseMemory(tmp, tokens2);
+		tree::RankedTree tree2 = alib::XmlDataFactory::fromTokens<tree::RankedTree>(tokens2);
+
+		CPPUNIT_ASSERT( tree == tree2 );
+		std::cout << std::endl;
+		tree2.getRoot().nicePrint(std::cout);
+	}
+/*
+	std::string s = "a2a2a2b1a2c0c0c0c0c0";
+	int itmp = 0;
+	tree::RankedNode * node = prefixToNode(s, itmp);
+	std::set<alphabet::RankedSymbol> al;
+	for (unsigned i = 0; i < s.length(); i += 2) al.insert(alphabet::RankedSymbol(s[i], (int) (s[i+1] - '0')));
+	tree::RankedTree t(al, std::move(*node));
+	alib::XmlDataFactory::toStdout(t);
+*/
+}
+
+void TreeTest::testRankedTreeCompare() {
+/*
+	L=(a(2), b(1), c(0))
+
+	\-1.a(2)
+	  |
+	  |-2.b(1)
+	  | |
+	  | \-3.c(0)
+	  |
+	  \-4.c(0)
+
+	\-5.a(2)
+	  |
+	  |-6.c(0)
+	  |
+	  \-7.b(1)
+	    |
+	    \-8.c(0)
+*/
+	const alphabet::RankedSymbol a ('a', 2);
+	const alphabet::RankedSymbol b ('b', 1);
+	const alphabet::RankedSymbol c ('c', 0);
+
+	const std::set<alphabet::RankedSymbol> alphabet {a, b, c};
+
+	std::vector<tree::RankedNode *> children3 (0);
+	tree::RankedNode * node3 = new tree::RankedNode(c, children3);
+	std::vector<tree::RankedNode *> children4 (0);
+	tree::RankedNode * node4 = new tree::RankedNode(c, children4);
+	std::vector<tree::RankedNode *> children2 {node3};
+	tree::RankedNode * node2 = new tree::RankedNode(b, children2);
+	std::vector<tree::RankedNode *> children1 {node2, node4};
+	tree::RankedNode * node1 = new tree::RankedNode(a, children1);
+
+	std::vector<tree::RankedNode *> children6 (0);
+	tree::RankedNode * node6 = new tree::RankedNode(c, children6);
+	std::vector<tree::RankedNode *> children8 (0);
+	tree::RankedNode * node8 = new tree::RankedNode(c, children8);
+	std::vector<tree::RankedNode *> children7 {node8};
+	tree::RankedNode * node7 = new tree::RankedNode(b, children7);
+	std::vector<tree::RankedNode *> children5 {node6, node7};
+	tree::RankedNode * node5 = new tree::RankedNode(a, children5);
+
+	tree::RankedTree tree1(alphabet, std::move(*node1));
+	tree::RankedTree tree2(alphabet, std::move(*node5));
+
+	CPPUNIT_ASSERT( tree1 != tree2 );
+	CPPUNIT_ASSERT( tree1 < tree2 );
+	CPPUNIT_ASSERT( tree2 > tree1 );
+	CPPUNIT_ASSERT( !(tree1 > tree2) );
+}
+
+void TreeTest::testRankedTreeSymbolValidityCheck() {
+	alphabet::RankedSymbol a ('a', 2);
+	alphabet::RankedSymbol b ('b', 1);
+	alphabet::RankedSymbol c ('c', 0);
+	alphabet::RankedSymbol d ('d', 0);
+	alphabet::RankedSymbol e ('e', 0);
+
+	const std::set<alphabet::RankedSymbol> alphabet {a, b, c, e};
+
+	std::vector<tree::RankedNode *> children3 (0);
+	tree::RankedNode * node3 = new tree::RankedNode(d, children3);
+	std::vector<tree::RankedNode *> children4 (0);
+	tree::RankedNode * node4 = new tree::RankedNode(c, children4);
+	std::vector<tree::RankedNode *> children2 {node3};
+	tree::RankedNode * node2 = new tree::RankedNode(b, children2);
+	std::vector<tree::RankedNode *> children1 {node2, node4};
+	tree::RankedNode * node1 = new tree::RankedNode(a, children1);
+
+	CPPUNIT_ASSERT_THROW(tree::RankedTree tree1(alphabet, *node1), exception::AlibException);
+
+	std::vector<tree::RankedNode *> children6 (0);
+	tree::RankedNode * node6 = new tree::RankedNode(e, children6);
+	std::vector<tree::RankedNode *> children8 (0);
+	tree::RankedNode * node8 = new tree::RankedNode(c, children8);
+	std::vector<tree::RankedNode *> children7 {node8};
+	tree::RankedNode * node7 = new tree::RankedNode(b, children7);
+	std::vector<tree::RankedNode *> children5 {node6, node7};
+	tree::RankedNode * node5 = new tree::RankedNode(a, children5);
+
+	tree::RankedTree * tree = NULL;
+	CPPUNIT_ASSERT_NO_THROW(tree = new tree::RankedTree(alphabet, std::move(*node5)));
+	CPPUNIT_ASSERT_NO_THROW(tree -> getRoot().getChildren()[0] -> setSymbol(c));
+	CPPUNIT_ASSERT_THROW(tree -> getRoot().getChildren()[1] -> setSymbol(d), exception::AlibException);
+	CPPUNIT_ASSERT_THROW(tree -> getRoot().getChildren()[0] -> setSymbol(a), exception::AlibException);
+	CPPUNIT_ASSERT_THROW(tree -> removeRankedSymbol(a), exception::AlibException);
+	CPPUNIT_ASSERT(tree -> removeRankedSymbol(e));
+	delete tree;
+}
+
+void TreeTest::testRankedTreeSubtreeSwitch() {
+	alphabet::RankedSymbol a ('a', 2);
+	alphabet::RankedSymbol b ('b', 1);
+	alphabet::RankedSymbol c ('c', 0);
+	alphabet::RankedSymbol d ('d', 0);
+
+	const std::set<alphabet::RankedSymbol> alphabet1 {a, b, c};
+	const std::set<alphabet::RankedSymbol> alphabet2 {a, b, c, d};
+
+	std::vector<tree::RankedNode *> children3 (0);
+	tree::RankedNode * node3 = new tree::RankedNode(c, children3);
+	std::vector<tree::RankedNode *> children4 (0);
+	tree::RankedNode * node4 = new tree::RankedNode(c, children4);
+	std::vector<tree::RankedNode *> children2 {node3};
+	tree::RankedNode * node2 = new tree::RankedNode(b, children2);
+	std::vector<tree::RankedNode *> children1 {node2, node4};
+	tree::RankedNode * node1 = new tree::RankedNode(a, children1);
+
+	std::vector<tree::RankedNode *> children6 (0);
+	tree::RankedNode * node6 = new tree::RankedNode(d, children6);
+	std::vector<tree::RankedNode *> children8 (0);
+	tree::RankedNode * node8 = new tree::RankedNode(c, children8);
+	std::vector<tree::RankedNode *> children7 {node8};
+	tree::RankedNode * node7 = new tree::RankedNode(b, children7);
+	std::vector<tree::RankedNode *> children5 {node6, node7};
+	tree::RankedNode * node5 = new tree::RankedNode(a, children5);
+
+	tree::RankedTree tree1(alphabet1, std::move(*node1));
+	tree::RankedTree tree1Copy (tree1);
+	tree::RankedTree tree2(alphabet2, std::move(*node5));
+	tree::RankedTree tree2Copy (tree2);
+
+	tree1.getRoot().getChildren()[0] -> getChildren()[0] -> switchSubtree(tree2.getRoot().getChildren()[1]);
+	tree1.getRoot().getChildren()[0] -> getChildren()[0] -> switchSubtree(tree2.getRoot().getChildren()[1]);
+
+	CPPUNIT_ASSERT(tree1 == tree1Copy);
+	CPPUNIT_ASSERT(tree2 == tree2Copy);
+	CPPUNIT_ASSERT_THROW(tree1.getRoot().getChildren()[1] -> switchSubtree(tree2.getRoot().getChildren()[0]), exception::AlibException);
+
+	tree::RankedTree tree3(tree1Copy);
+	tree::RankedTree tree4(tree2Copy);
+
+	tree4.getRoot().getChildren()[0] -> setSymbol(c);
+
+	tree3.getRoot().nicePrint();
+	std::cout << std::endl;
+	tree4.getRoot().nicePrint();
+
+	tree3.getRoot().switchSubtree(&tree4.getRoot());
+
+	CPPUNIT_ASSERT(tree3.getRoot() < tree2Copy.getRoot());
+	CPPUNIT_ASSERT(tree4.getRoot() == tree1Copy.getRoot());
+
+}
+
+void TreeTest::testUnrankedTreeParser() {
+/*
+	L=(a, b, c)
+
+	\-1.a
+	  |
+	  |-2.b
+	  | |
+	  | \-3.c
+	  |
+	  \-4.c
+*/
+	const alphabet::LabeledSymbol a ('a');
+	const alphabet::LabeledSymbol b ('b');
+	const alphabet::LabeledSymbol c ('c');
+
+	const std::set<alphabet::LabeledSymbol> alphabet {a, b, c};
+
+	std::list<tree::UnrankedNode *> children3;
+	tree::UnrankedNode * node3 = new tree::UnrankedNode(c, children3);
+	std::list<tree::UnrankedNode *> children4;
+	tree::UnrankedNode * node4 = new tree::UnrankedNode(c, children4);
+	std::list<tree::UnrankedNode *> children2 {node3};
+	tree::UnrankedNode * node2 = new tree::UnrankedNode(b, children2);
+	std::list<tree::UnrankedNode *> children1 {node2, node4};
+	tree::UnrankedNode * node1 = new tree::UnrankedNode(a, children1);
+
+	tree::UnrankedTree tree(alphabet, std::move(*node1));
+
+	CPPUNIT_ASSERT( tree == tree );
+	tree.getRoot().nicePrint(std::cout);
+	{
+		std::deque<sax::Token> tokens = alib::XmlDataFactory::toTokens(tree);
+		std::string tmp;
+		sax::SaxComposeInterface::printMemory(tmp, tokens);
+		std::cout << std::endl << tmp << std::endl << std::endl;
+
+		std::deque<sax::Token> tokens2;
+		sax::SaxParseInterface::parseMemory(tmp, tokens2);
+		tree::UnrankedTree tree2 = alib::XmlDataFactory::fromTokens<tree::UnrankedTree>(tokens2);
+
+		CPPUNIT_ASSERT( tree == tree2 );
+		std::cout << std::endl;
+		tree2.getRoot().nicePrint(std::cout);
+	}
+}
+
+void TreeTest::testUnrankedTreeCompare() {
+/*
+	L=(a, b, c)
+
+	\-1.a
+	  |
+	  |-2.b
+	  | |
+	  | \-3.c
+	  |
+	  \-4.c
+
+	\-5.a
+	  |
+	  |-6.c
+	  |
+	  \-7.b
+	    |
+	    \-8.c
+*/
+	const alphabet::LabeledSymbol a ('a');
+	const alphabet::LabeledSymbol b ('b');
+	const alphabet::LabeledSymbol c ('c');
+
+	const std::set<alphabet::LabeledSymbol> alphabet {a, b, c};
+
+	std::list<tree::UnrankedNode *> children3;
+	tree::UnrankedNode * node3 = new tree::UnrankedNode(c, children3);
+	std::list<tree::UnrankedNode *> children4;
+	tree::UnrankedNode * node4 = new tree::UnrankedNode(c, children4);
+	std::list<tree::UnrankedNode *> children2 {node3};
+	tree::UnrankedNode * node2 = new tree::UnrankedNode(b, children2);
+	std::list<tree::UnrankedNode *> children1 {node2, node4};
+	tree::UnrankedNode * node1 = new tree::UnrankedNode(a, children1);
+
+	std::list<tree::UnrankedNode *> children6;
+	tree::UnrankedNode * node6 = new tree::UnrankedNode(c, children6);
+	std::list<tree::UnrankedNode *> children8;
+	tree::UnrankedNode * node8 = new tree::UnrankedNode(c, children8);
+	std::list<tree::UnrankedNode *> children7 {node8};
+	tree::UnrankedNode * node7 = new tree::UnrankedNode(b, children7);
+	std::list<tree::UnrankedNode *> children5 {node6, node7};
+	tree::UnrankedNode * node5 = new tree::UnrankedNode(a, children5);
+
+	tree::UnrankedTree tree1(alphabet, std::move(*node1));
+	tree::UnrankedTree tree2(alphabet, std::move(*node5));
+
+	CPPUNIT_ASSERT( tree1 != tree2 );
+	CPPUNIT_ASSERT( tree1 < tree2 );
+	CPPUNIT_ASSERT( tree2 > tree1 );
+	CPPUNIT_ASSERT( !(tree1 > tree2) );
+}
+
+void TreeTest::testUnrankedTreeSymbolValidityCheck() {
+	alphabet::LabeledSymbol a ('a');
+	alphabet::LabeledSymbol b ('b');
+	alphabet::LabeledSymbol c ('c');
+	alphabet::LabeledSymbol d ('d');
+	alphabet::LabeledSymbol e ('e');
+
+	const std::set<alphabet::LabeledSymbol> alphabet {a, b, c, e};
+
+	std::list<tree::UnrankedNode *> children3 (0);
+	tree::UnrankedNode * node3 = new tree::UnrankedNode(d, children3);
+	std::list<tree::UnrankedNode *> children4 (0);
+	tree::UnrankedNode * node4 = new tree::UnrankedNode(c, children4);
+	std::list<tree::UnrankedNode *> children2 {node3};
+	tree::UnrankedNode * node2 = new tree::UnrankedNode(b, children2);
+	std::list<tree::UnrankedNode *> children1 {node2, node4};
+	tree::UnrankedNode * node1 = new tree::UnrankedNode(a, children1);
+
+	CPPUNIT_ASSERT_THROW(tree::UnrankedTree tree1(alphabet, *node1), exception::AlibException);
+
+	std::list<tree::UnrankedNode *> children6 (0);
+	tree::UnrankedNode * node6 = new tree::UnrankedNode(e, children6);
+	std::list<tree::UnrankedNode *> children8 (0);
+	tree::UnrankedNode * node8 = new tree::UnrankedNode(c, children8);
+	std::list<tree::UnrankedNode *> children7 {node8};
+	tree::UnrankedNode * node7 = new tree::UnrankedNode(b, children7);
+	std::list<tree::UnrankedNode *> children5 {node6, node7};
+	tree::UnrankedNode * node5 = new tree::UnrankedNode(a, children5);
+
+	tree::UnrankedTree * tree = NULL;
+	CPPUNIT_ASSERT_NO_THROW(tree = new tree::UnrankedTree(alphabet, std::move(*node5)));
+	CPPUNIT_ASSERT_NO_THROW((*tree -> getRoot().getChildren().begin()) -> setSymbol(c));
+	CPPUNIT_ASSERT_THROW((*tree -> getRoot().getChildren().begin()) -> setSymbol(d), exception::AlibException);
+	CPPUNIT_ASSERT_NO_THROW((*(++tree -> getRoot().getChildren().begin())) -> setSymbol(a));
+	CPPUNIT_ASSERT_THROW(tree -> removeSymbol(a), exception::AlibException);
+	CPPUNIT_ASSERT(tree -> removeSymbol(e));
+	delete tree;
+}
+
+void TreeTest::testUnrankedTreeSubtreeSwitch() {
+	alphabet::LabeledSymbol a ('a');
+	alphabet::LabeledSymbol b ('b');
+	alphabet::LabeledSymbol c ('c');
+	alphabet::LabeledSymbol d ('d');
+
+	const std::set<alphabet::LabeledSymbol> alphabet1 {a, b, c};
+	const std::set<alphabet::LabeledSymbol> alphabet2 {a, b, c, d};
+
+	std::list<tree::UnrankedNode *> children3;
+	tree::UnrankedNode * node3 = new tree::UnrankedNode(c, children3);
+	std::list<tree::UnrankedNode *> children4;
+	tree::UnrankedNode * node4 = new tree::UnrankedNode(c, children4);
+	std::list<tree::UnrankedNode *> children2 {node3};
+	tree::UnrankedNode * node2 = new tree::UnrankedNode(b, children2);
+	std::list<tree::UnrankedNode *> children1 {node2, node4};
+	tree::UnrankedNode * node1 = new tree::UnrankedNode(a, children1);
+
+	std::list<tree::UnrankedNode *> children6;
+	tree::UnrankedNode * node6 = new tree::UnrankedNode(d, children6);
+	std::list<tree::UnrankedNode *> children8;
+	tree::UnrankedNode * node8 = new tree::UnrankedNode(c, children8);
+	std::list<tree::UnrankedNode *> children7 {node8};
+	tree::UnrankedNode * node7 = new tree::UnrankedNode(b, children7);
+	std::list<tree::UnrankedNode *> children5 {node6, node7};
+	tree::UnrankedNode * node5 = new tree::UnrankedNode(a, children5);
+
+	tree::UnrankedTree tree1(alphabet1, std::move(*node1));
+	tree::UnrankedTree tree1Copy (tree1);
+	tree::UnrankedTree tree2(alphabet2, std::move(*node5));
+	tree::UnrankedTree tree2Copy (tree2);
+
+	(*(*tree1.getRoot().getChildren().begin()) -> getChildren().begin()) -> switchSubtree(*(++tree2.getRoot().getChildren().begin()));
+	(*(*tree1.getRoot().getChildren().begin()) -> getChildren().begin()) -> switchSubtree(*(++tree2.getRoot().getChildren().begin()));
+
+	CPPUNIT_ASSERT(tree1 == tree1Copy);
+	CPPUNIT_ASSERT(tree2 == tree2Copy);
+	CPPUNIT_ASSERT_THROW((*(++tree1.getRoot().getChildren().begin())) -> switchSubtree(*tree2.getRoot().getChildren().begin()), exception::AlibException);
+
+	tree::UnrankedTree tree3(tree1Copy);
+	tree::UnrankedTree tree4(tree2Copy);
+
+	(*tree4.getRoot().getChildren().begin()) -> setSymbol(c);
+
+	tree3.getRoot().nicePrint();
+	std::cout << std::endl;
+	tree4.getRoot().nicePrint();
+
+	tree3.getRoot().switchSubtree(&tree4.getRoot());
+
+	CPPUNIT_ASSERT(tree3.getRoot() < tree2Copy.getRoot());
+	CPPUNIT_ASSERT(tree4.getRoot() == tree1Copy.getRoot());
+}
+
diff --git a/alib2data/test-src/tree/TreeTest.h b/alib2data/test-src/tree/TreeTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..842c4a60183fed811bedfceb67fd2be0fcc63f0e
--- /dev/null
+++ b/alib2data/test-src/tree/TreeTest.h
@@ -0,0 +1,34 @@
+#ifndef TREE_TEST_H_
+#define TREE_TEST_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class TreeTest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( TreeTest );
+  CPPUNIT_TEST( testRankedTreeParser );
+  CPPUNIT_TEST( testRankedTreeCompare );
+  CPPUNIT_TEST( testRankedTreeSymbolValidityCheck );
+  CPPUNIT_TEST( testRankedTreeSubtreeSwitch );
+  CPPUNIT_TEST( testUnrankedTreeParser );
+  CPPUNIT_TEST( testUnrankedTreeCompare );
+  CPPUNIT_TEST( testUnrankedTreeSymbolValidityCheck );
+  CPPUNIT_TEST( testUnrankedTreeSubtreeSwitch );
+  CPPUNIT_TEST_SUITE_END();
+
+public:
+  void setUp();
+  void tearDown();
+
+  void testRankedTreeParser();
+  void testRankedTreeCompare();
+  void testRankedTreeSymbolValidityCheck();
+  void testRankedTreeSubtreeSwitch();
+
+  void testUnrankedTreeParser();
+  void testUnrankedTreeCompare();
+  void testUnrankedTreeSymbolValidityCheck();
+  void testUnrankedTreeSubtreeSwitch();
+};
+
+#endif  // TREE_TEST_H_
diff --git a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp
index 148ff0fcc9dc9a9eb933bd5d6c09467ff890e80f..6b6ac7f985bbf7c55067fd90d09c369021c4af2a 100644
--- a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp
+++ b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp
@@ -178,6 +178,14 @@ void AllEpsilonClosure::Visit(void* data, const CompactNFA& automaton) const {
 	out = std::move(this->allEpsilonClosure(automaton));
 }
 
+void AllEpsilonClosure::Visit(void*, const DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void AllEpsilonClosure::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 void AllEpsilonClosure::Visit(void*, const DPDA&) const {
 	throw exception::AlibException("Unsupported automaton type DPDA");
 }
diff --git a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h
index feea7164db559dc3e58e06c2bf0619ccf34d9d76..7b29e957aef8a45e2c6fc525dbb17cdfc0a3e3ce 100644
--- a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h
+++ b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h
@@ -41,6 +41,8 @@ private:
 	void Visit(void*, const DFA& automaton) const;
 	void Visit(void*, const ExtendedNFA& automaton) const;
 	void Visit(void*, const CompactNFA& automaton) const;
+	void Visit(void*, const NFTA& automaton) const;
+	void Visit(void*, const DFTA& automaton) const;
 	void Visit(void*, const DPDA& automaton) const;
 	void Visit(void*, const SinglePopDPDA& automaton) const;
 	void Visit(void*, const InputDrivenDPDA& automaton) const;
diff --git a/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp b/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp
index 3070f632768a56bd3c95e4269604cbe6f6e69f6f..a4ccda4742fbc752bfe69d5fa6a37c771503964c 100644
--- a/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp
+++ b/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp
@@ -131,6 +131,14 @@ void ReachableStates::Visit(void* data, const CompactNFA& automaton) const {
 	out = std::move(this->reachableStates(automaton));
 }
 
+void ReachableStates::Visit(void*, const DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void ReachableStates::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 void ReachableStates::Visit(void*, const DPDA&) const {
 	throw exception::AlibException("Unsupported automaton type DPDA");
 }
diff --git a/alib2elgo/src/automaton/properties/efficient/ReachableStates.h b/alib2elgo/src/automaton/properties/efficient/ReachableStates.h
index 6b52d3990d4d7056b8f27804de7f719cb6a25dc9..c58dbbd5246e920b69a71e8badc122c78ea60ce3 100644
--- a/alib2elgo/src/automaton/properties/efficient/ReachableStates.h
+++ b/alib2elgo/src/automaton/properties/efficient/ReachableStates.h
@@ -38,6 +38,8 @@ private:
 	void Visit(void*, const DFA& automaton) const;
 	void Visit(void*, const ExtendedNFA& automaton) const;
 	void Visit(void*, const CompactNFA& automaton) const;
+	void Visit(void*, const NFTA& automaton) const;
+	void Visit(void*, const DFTA& automaton) const;
 	void Visit(void*, const DPDA& automaton) const;
 	void Visit(void*, const SinglePopDPDA& automaton) const;
 	void Visit(void*, const InputDrivenDPDA& automaton) const;
diff --git a/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp b/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp
index 446ee0da44f08473918b5fe14488edc2af447d34..e7e6684d28545c98d3d18d0e6b6bff5d96ce3635 100644
--- a/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp
+++ b/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp
@@ -111,6 +111,14 @@ void UsefullStates::Visit(void* data, const CompactNFA& automaton) const {
 	out = std::move(this->usefullStates(automaton));
 }
 
+void UsefullStates::Visit(void*, const DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void UsefullStates::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 void UsefullStates::Visit(void*, const DPDA&) const {
 	throw exception::AlibException("Unsupported automaton type DPDA");
 }
diff --git a/alib2elgo/src/automaton/properties/efficient/UsefullStates.h b/alib2elgo/src/automaton/properties/efficient/UsefullStates.h
index 1a4117afcaeb63abbbd234485a06992a134ac824..46a1049392a14bdf2a74fe8b70800ba170e6d9f5 100644
--- a/alib2elgo/src/automaton/properties/efficient/UsefullStates.h
+++ b/alib2elgo/src/automaton/properties/efficient/UsefullStates.h
@@ -39,6 +39,8 @@ private:
 	void Visit(void*, const ExtendedNFA& automaton) const;
 	void Visit(void*, const CompactNFA& automaton) const;
 	void Visit(void*, const DPDA& automaton) const;
+	void Visit(void*, const NFTA& automaton) const;
+	void Visit(void*, const DFTA& automaton) const;
 	void Visit(void*, const SinglePopDPDA& automaton) const;
 	void Visit(void*, const InputDrivenDPDA& automaton) const;
 	void Visit(void*, const InputDrivenNPDA& automaton) const;
diff --git a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.cpp b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.cpp
index 9a57df5a5f9b691caf0f03cffa746b82757c4f5b..6ec1e00cd3efb8102e87f20964486d738ba31093 100644
--- a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.cpp
+++ b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.cpp
@@ -98,6 +98,14 @@ void EpsilonRemoverIncoming::Visit(void* data, const automaton::DFA& automaton)
 	out = new automaton::Automaton(this->remove(automaton));
 }
 
+void EpsilonRemoverIncoming::Visit(void*, const DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void EpsilonRemoverIncoming::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 void EpsilonRemoverIncoming::Visit(void*, const automaton::ExtendedNFA& ) const {
 	throw exception::AlibException("Unsupported automaton type ExtendedNFA");
 }
diff --git a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.h b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.h
index 134c41bc91c1f05681ba9a03d36a510349b7d052..0165d210d1af42286ec8816e75673fcb68025e25 100644
--- a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.h
+++ b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.h
@@ -44,6 +44,8 @@ private:
 	void Visit(void*, const automaton::DFA& automaton) const;
 	void Visit(void*, const automaton::ExtendedNFA& automaton) const;
 	void Visit(void*, const automaton::CompactNFA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
 	void Visit(void*, const automaton::DPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopDPDA& automaton) const;
 	void Visit(void*, const automaton::InputDrivenDPDA& automaton) const;
diff --git a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.cpp b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.cpp
index d44d0af0d91e2ccbd08009545d1d26b1798509e0..871d1674e751faed45fe4c4e3c5d2f58db06a39c 100644
--- a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.cpp
+++ b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.cpp
@@ -82,6 +82,14 @@ void EpsilonRemoverOutgoing::Visit(void* data, const automaton::DFA& automaton)
 	out = new automaton::Automaton(this->remove(automaton));
 }
 
+void EpsilonRemoverOutgoing::Visit(void*, const DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void EpsilonRemoverOutgoing::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 void EpsilonRemoverOutgoing::Visit(void*, const automaton::ExtendedNFA& ) const {
 	throw exception::AlibException("Unsupported automaton type ExtendedNFA");
 }
diff --git a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.h b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.h
index 17ec208f79bb8e15031514067170f9707baf3aaf..3ae5ea98172c6fa5dd399621627581f4ea50f064 100644
--- a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.h
+++ b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.h
@@ -44,6 +44,8 @@ private:
 	void Visit(void*, const automaton::DFA& automaton) const;
 	void Visit(void*, const automaton::ExtendedNFA& automaton) const;
 	void Visit(void*, const automaton::CompactNFA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
 	void Visit(void*, const automaton::DPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopDPDA& automaton) const;
 	void Visit(void*, const automaton::InputDrivenDPDA& automaton) const;
diff --git a/alib2elgo/src/automaton/simplify/efficient/Trim.cpp b/alib2elgo/src/automaton/simplify/efficient/Trim.cpp
index 627c532b2f93f285085a0369f1509e566a51739a..fd593234d290d1caaeef5729844b80486a8a5ab3 100644
--- a/alib2elgo/src/automaton/simplify/efficient/Trim.cpp
+++ b/alib2elgo/src/automaton/simplify/efficient/Trim.cpp
@@ -75,6 +75,14 @@ void Trim::Visit(void* data, const automaton::CompactNFA& automaton) const {
 	out = new automaton::Automaton(this->trim(automaton));
 }
 
+void Trim::Visit(void*, const DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void Trim::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 void Trim::Visit(void*, const automaton::DPDA&) const {
 	throw exception::AlibException("Unsupported automaton type DPDA");
 }
diff --git a/alib2elgo/src/automaton/simplify/efficient/Trim.h b/alib2elgo/src/automaton/simplify/efficient/Trim.h
index 8048d0cd9b6d94e2ad7e8d29db5c5f54a999430f..5a48ba8306a114aeb7827ac10d10a9428cf86fed 100644
--- a/alib2elgo/src/automaton/simplify/efficient/Trim.h
+++ b/alib2elgo/src/automaton/simplify/efficient/Trim.h
@@ -36,6 +36,8 @@ private:
 	void Visit(void*, const automaton::DFA& automaton) const;
 	void Visit(void*, const automaton::ExtendedNFA& automaton) const;
 	void Visit(void*, const automaton::CompactNFA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
 	void Visit(void*, const automaton::DPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopDPDA& automaton) const;
 	void Visit(void*, const automaton::InputDrivenDPDA& automaton) const;
diff --git a/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.cpp b/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.cpp
index f0b7c582ea1f31690796251ee3cdd937eb831e1b..9271cd4c59674930fb6fa5bcd68fa32359ed59ad 100644
--- a/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.cpp
+++ b/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.cpp
@@ -151,6 +151,14 @@ void UnreachableStatesRemover::Visit(void* data, const automaton::CompactNFA& au
 	out = new automaton::Automaton(this->remove(automaton));
 }
 
+void UnreachableStatesRemover::Visit(void*, const DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void UnreachableStatesRemover::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 void UnreachableStatesRemover::Visit(void*, const automaton::DPDA&) const {
 	throw exception::AlibException("Unsupported automaton type DPDA");
 }
diff --git a/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h b/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h
index 4fa148ed79672df6a2f38ef01ed4585adb2fe3db..4abec63a184f60735b707366a4c878be69f6297d 100644
--- a/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h
+++ b/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h
@@ -36,6 +36,8 @@ private:
 	void Visit(void*, const automaton::DFA& automaton) const;
 	void Visit(void*, const automaton::ExtendedNFA& automaton) const;
 	void Visit(void*, const automaton::CompactNFA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
 	void Visit(void*, const automaton::DPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopDPDA& automaton) const;
 	void Visit(void*, const automaton::InputDrivenDPDA& automaton) const;
diff --git a/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.cpp b/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.cpp
index 536ed54becb0a4358eb5144e91beac3f96eb80cf..8299c4540a109aa8e38656288ae8c219bdfa6970 100644
--- a/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.cpp
+++ b/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.cpp
@@ -160,6 +160,14 @@ void UselessStatesRemover::Visit(void* data, const automaton::CompactNFA& automa
 	out = new automaton::Automaton(this->remove(automaton));
 }
 
+void UselessStatesRemover::Visit(void*, const DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void UselessStatesRemover::Visit(void*, const NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 void UselessStatesRemover::Visit(void*, const automaton::DPDA&) const {
 	throw exception::AlibException("Unsupported automaton type DPDA");
 }
diff --git a/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h b/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h
index df0b85d6f03bf7c13d33bffd630d1a8bc032b363..14877104fd8204bc78fbdf90355a3e6e38f7cf5b 100644
--- a/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h
+++ b/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h
@@ -36,6 +36,8 @@ private:
 	void Visit(void*, const automaton::DFA& automaton) const;
 	void Visit(void*, const automaton::ExtendedNFA& automaton) const;
 	void Visit(void*, const automaton::CompactNFA& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
 	void Visit(void*, const automaton::DPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopDPDA& automaton) const;
 	void Visit(void*, const automaton::InputDrivenDPDA& automaton) const;
diff --git a/arand2/src/arand.cpp b/arand2/src/arand.cpp
index 925c1d65cc975c6d4b534cd9299d6256ba4e255a..761c2e61ed574831a5bd8a4c45af0b1731525918 100644
--- a/arand2/src/arand.cpp
+++ b/arand2/src/arand.cpp
@@ -10,10 +10,13 @@
 #include <automaton/FSM/NFA.h>
 #include <regexp/unbounded/UnboundedRegExp.h>
 #include <factory/XmlDataFactory.hpp>
+#include <tree/RankedTree/RankedTree.h>
+#include <tree/UnrankedTree/UnrankedTree.h>
 #include "automaton/generate/RandomAutomatonFactory.h"
 #include "grammar/generate/RandomGrammarFactory.h"
 #include "regexp/generate/RandomRegExpFactory.h"
 #include "string/generate/RandomStringFactory.h"
+#include "tree/generate/RandomTreeFactory.h"
 
 int main(int argc, char* argv[]) {
 	try {
@@ -24,6 +27,8 @@ int main(int argc, char* argv[]) {
 		allowed.push_back("CFG");
 		allowed.push_back("RE");
 		allowed.push_back("ST");
+		allowed.push_back("UT");
+		allowed.push_back("RT");
 		TCLAP::ValuesConstraint<std::string> allowedVals( allowed );
 
 		TCLAP::ValueArg<std::string> type(	"t",	"type",		"Type of generated structure",			true,	"FSM",	&allowedVals);
@@ -38,6 +43,9 @@ int main(int argc, char* argv[]) {
 		TCLAP::ValueArg<int> nonterminals(	"",	"nonterminals",	"Number of grammar's nononterminals",		false,	5,	"integer");
 		cmd.add( nonterminals );
 
+		TCLAP::ValueArg<int> nodes(		"",	"nodes",	"Number of automaton's or tree nodes",		false,	5,	"integer");
+		cmd.add( nodes );
+
 		TCLAP::ValueArg<int> states(		"",	"states",	"Number of automaton's states",			false,	5,	"integer");
 		cmd.add( states );
 
@@ -50,6 +58,12 @@ int main(int argc, char* argv[]) {
 		TCLAP::ValueArg<int> length(		"",	"length",	"Length of the string",				false,	5,	"integer");
 		cmd.add( length );
 
+		TCLAP::ValueArg<int> depth(		"",	"depth",	"Depth of the regexp or tree",			false,	5,	"integer");
+		cmd.add( depth );
+
+		TCLAP::ValueArg<int> maxRank(		"",	"rank",		"Maximal rank of tree nodes",			false,	5,	"integer");
+		cmd.add( maxRank );
+
 		cmd.parse(argc,argv);
 
 		if(!type.isSet()) throw exception::AlibException("Type is not defined.");
@@ -98,6 +112,12 @@ int main(int argc, char* argv[]) {
 
 			string::LinearString res = string::generate::RandomStringFactory::generateLinearString(length.getValue(), alphabetSize.getValue() );
 			alib::XmlDataFactory::toStdout(res);
+		} else if( type.getValue() == "UT" ) {
+			tree::UnrankedTree res = tree::generate::RandomTreeFactory::generateUnrankedTree(depth.getValue(), nodes.getValue(), alphabetSize.getValue(), maxRank.getValue());
+			alib::XmlDataFactory::toStdout(res);
+		} else if( type.getValue() == "RT" ) {
+			tree::RankedTree res = tree::generate::RandomTreeFactory::generateRankedTree(depth.getValue(), nodes.getValue(), alphabetSize.getValue(), maxRank.getValue());
+			alib::XmlDataFactory::toStdout(res);
 		} else {
 			throw exception::AlibException("Invalid type.");
 		}
diff --git a/arun2/src/arun.cpp b/arun2/src/arun.cpp
index 8b6c58ba593a3eff73d908e925e5af15c1af4c31..824ee5c9346d97ae2e5b1ccd822dedb46c512d14 100644
--- a/arun2/src/arun.cpp
+++ b/arun2/src/arun.cpp
@@ -11,11 +11,15 @@
 #include <factory/XmlDataFactory.hpp>
 #include <exception/AlibException.h>
 #include <string/String.h>
+#include <object/Object.h>
+#include <tree/RankedTree/RankedTree.h>
 #include <automaton/Automaton.h>
 #include <automaton/run/Accept.h>
 #include <automaton/run/Result.h>
 #include <automaton/run/Occurrences.h>
 
+#include <iostream>
+
 int main(int argc, char* argv[]) {
 	try {
 		TCLAP::CmdLine cmd("Automaton run binary", ' ', "0.01");
@@ -60,18 +64,18 @@ int main(int argc, char* argv[]) {
 		}
 
 		if( type.getValue() == "occurrences") {
-			string::LinearString input = alib::XmlDataFactory::fromTokens<string::LinearString>(inputTokens);
+			alib::Object input = alib::XmlDataFactory::fromTokens<alib::Object>(inputTokens);
 			automaton::Automaton automaton = alib::XmlDataFactory::fromTokens<automaton::Automaton>(automatonTokens);
 			std::set<unsigned> res = automaton::run::Occurrences::occurrences(automaton, input);
 			alib::XmlDataFactory::toStdout( res );
 			return 0;
 		} else if( type.getValue() == "accept") {
-			string::LinearString input = alib::XmlDataFactory::fromTokens<string::LinearString>(inputTokens);
+			alib::Object input = alib::XmlDataFactory::fromTokens<alib::Object>(inputTokens);
 			automaton::Automaton automaton = alib::XmlDataFactory::fromTokens<automaton::Automaton>(automatonTokens);
 			bool res = automaton::run::Accept::accept(automaton, input);
 			alib::XmlDataFactory::toStdout( res );
 		} else if( type.getValue() == "result") {
-			string::LinearString input = alib::XmlDataFactory::fromTokens<string::LinearString>(inputTokens);
+			alib::Object input = alib::XmlDataFactory::fromTokens<alib::Object>(inputTokens);
 			automaton::Automaton automaton = alib::XmlDataFactory::fromTokens<automaton::Automaton>(automatonTokens);
 			label::Label res = automaton::run::Result::result(automaton, input);
 			alib::XmlDataFactory::toStdout( res );
diff --git a/astat2/src/AutomataStat.cpp b/astat2/src/AutomataStat.cpp
index 01c0aafdc9268166185e28498b5d7193630963cd..e875d94608b040b5302b159fd2a722347c590a01 100644
--- a/astat2/src/AutomataStat.cpp
+++ b/astat2/src/AutomataStat.cpp
@@ -242,5 +242,13 @@ void AutomataStat::Visit(void*, const automaton::OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
+void AutomataStat::Visit(void*, const automaton::DFTA&) const {
+	throw exception::AlibException("Unsupported automaton type DFTA");
+}
+
+void AutomataStat::Visit(void*, const automaton::NFTA&) const {
+	throw exception::AlibException("Unsupported automaton type NFTA");
+}
+
 const AutomataStat AutomataStat::AUTOMATA_STAT;
 
diff --git a/astat2/src/AutomataStat.h b/astat2/src/AutomataStat.h
index cdcded194f47bd3091c82d3397560be704ddbda2..1f992e381fe6e6ec932977817ff1245ba25f78d2 100644
--- a/astat2/src/AutomataStat.h
+++ b/astat2/src/AutomataStat.h
@@ -42,6 +42,8 @@ private:
 	void Visit(void*, const automaton::NPDA& automaton) const;
 	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
 	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+	void Visit(void*, const automaton::NFTA& automaton) const;
+	void Visit(void*, const automaton::DFTA& automaton) const;
 
 	static const AutomataStat AUTOMATA_STAT;
 };
diff --git a/examples2/automaton/DFTA.xml b/examples2/automaton/DFTA.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4183107b6da64f28bc0a350d6a8a200647dab6fe
--- /dev/null
+++ b/examples2/automaton/DFTA.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<DFTA><states><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></states><rankedInputAlphabet><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol><RankedSymbol><PrimitiveLabel><Character>b</Character></PrimitiveLabel><Integer>1</Integer></RankedSymbol><RankedSymbol><PrimitiveLabel><Character>c</Character></PrimitiveLabel><Integer>0</Integer></RankedSymbol></rankedInputAlphabet><finalStates><LabelSetLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></finalStates><transitions><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></from><to><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></from><to><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></from><to><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><LabelSetLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></from><to><LabelSetLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel></LabelSetLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><LabelSetLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></from><to><LabelSetLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel></LabelSetLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><LabelSetLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></from><to><LabelSetLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel></LabelSetLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></from><to><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></from><to><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></from><to><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></from><to><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></from><to><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></from><to><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>b</Character></PrimitiveLabel><Integer>1</Integer></RankedSymbol></input><from><LabelSetLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel></LabelSetLabel></from><to><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel></LabelSetLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>b</Character></PrimitiveLabel><Integer>1</Integer></RankedSymbol></input><from><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></from><to><LabelSetLabel><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel></LabelSetLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>c</Character></PrimitiveLabel><Integer>0</Integer></RankedSymbol></input><from/><to><LabelSetLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></LabelSetLabel></to></transition></transitions></DFTA>
diff --git a/examples2/automaton/NFTA.xml b/examples2/automaton/NFTA.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3896e43e27766e049a5ff89d4c0101b013ad8732
--- /dev/null
+++ b/examples2/automaton/NFTA.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<NFTA><states><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></states><rankedInputAlphabet><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol><RankedSymbol><PrimitiveLabel><Character>b</Character></PrimitiveLabel><Integer>1</Integer></RankedSymbol><RankedSymbol><PrimitiveLabel><Character>c</Character></PrimitiveLabel><Integer>0</Integer></RankedSymbol></rankedInputAlphabet><finalStates><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></finalStates><transitions><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></from><to><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></from><to><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol></input><from><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></from><to><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>b</Character></PrimitiveLabel><Integer>1</Integer></RankedSymbol></input><from><PrimitiveLabel><Integer>2</Integer></PrimitiveLabel></from><to><PrimitiveLabel><Integer>1</Integer></PrimitiveLabel></to></transition><transition><input><RankedSymbol><PrimitiveLabel><Character>c</Character></PrimitiveLabel><Integer>0</Integer></RankedSymbol></input><from/><to><PrimitiveLabel><Integer>3</Integer></PrimitiveLabel></to></transition></transitions></NFTA>
diff --git a/examples2/tree/RankedTree.xml b/examples2/tree/RankedTree.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cfa71eadf93bbdfe514b1bbdc9dce5176bf4a946
--- /dev/null
+++ b/examples2/tree/RankedTree.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0"?>
+<RankedTree><rankedAlphabet><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol><RankedSymbol><PrimitiveLabel><Character>b</Character></PrimitiveLabel><Integer>1</Integer></RankedSymbol><RankedSymbol><PrimitiveLabel><Character>c</Character></PrimitiveLabel><Integer>0</Integer></RankedSymbol></rankedAlphabet><rankedNode><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol><rankedNode><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol><rankedNode><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol><rankedNode><RankedSymbol><PrimitiveLabel><Character>b</Character></PrimitiveLabel><Integer>1</Integer></RankedSymbol><rankedNode><RankedSymbol><PrimitiveLabel><Character>a</Character></PrimitiveLabel><Integer>2</Integer></RankedSymbol><rankedNode><RankedSymbol><PrimitiveLabel><Character>c</Character></PrimitiveLabel><Integer>0</Integer></RankedSymbol></rankedNode><rankedNode><RankedSymbol><PrimitiveLabel><Character>c</Character></PrimitiveLabel><Integer>0</Integer></RankedSymbol></rankedNode></rankedNode></rankedNode><rankedNode><RankedSymbol><PrimitiveLabel><Character>c</Character></PrimitiveLabel><Integer>0</Integer></RankedSymbol></rankedNode></rankedNode><rankedNode><RankedSymbol><PrimitiveLabel><Character>c</Character></PrimitiveLabel><Integer>0</Integer></RankedSymbol></rankedNode></rankedNode><rankedNode><RankedSymbol><PrimitiveLabel><Character>c</Character></PrimitiveLabel><Integer>0</Integer></RankedSymbol></rankedNode></rankedNode></RankedTree>
diff --git a/makefile b/makefile
index ceb618d20e7e22ba0f1a2533a61de56dd51d73e1..43a811f4dab8cf60555ee763c1bfe1ba787a132c 100644
--- a/makefile
+++ b/makefile
@@ -27,6 +27,7 @@ SUBDIRS_BINS = aecho2 \
 		astat2 \
 		astringology2 \
 		atrim2 \
+		tniceprint \
 
 
 ifneq (3.81, $(firstword $(sort $(MAKE_VERSION) 3.81)))
@@ -42,6 +43,7 @@ CPPUNIT_EXISTS = $(shell g++ -c -o /dev/null -xc++ - <<< \\\#include\ \<cppunit/
 ifneq (0, $(CPPUNIT_EXISTS))
 $(error You need cppunit installed)
 endif
+
 CPPUNIT_SO_TMP = $(shell ld --verbose | grep SEARCH | tr \  \\\n | sed s/SEARCH_DIR//g | sed s/\(\\\"//g | sed s/\\\"\)\\\;//g | sed s/^=//g | sort -u | sed \s/$$/\\/libcppunit.so/g\)
 CPPUNIT_SO_EXISTS = $(shell ls $(CPPUNIT_SO_TMP) 2>/dev/null | wc -l)
 ifeq (0, $(CPPUNIT_SO_EXISTS))
diff --git a/tests.examples.sh b/tests.examples.sh
index c4eeed3693a38d028cf6f21ac7c1c8ef650cc1ca..597b76937ff3a1430ca6ae27e2ab30cc6c2c5c21 100755
--- a/tests.examples.sh
+++ b/tests.examples.sh
@@ -125,4 +125,5 @@ runTest "automaton"
 runTest "grammar"
 runTest "regexp"
 runTest "string"
+runTest "tree"
 
diff --git a/tniceprint/makefile b/tniceprint/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d4d105b99aedc67657d4c7b39802510f9981aa65
--- /dev/null
+++ b/tniceprint/makefile
@@ -0,0 +1,128 @@
+SHELL:=/bin/bash
+EXECUTABLE:=tniceprint
+
+define NEW_LINE
+
+
+endef
+
+export NEW_LINE
+
+LDFLAGS_DEBUG:=-L../alib2std/lib-debug -L../alib2data/lib-debug -L../alib2algo/lib-debug -L../alib2elgo/lib-debug -rdynamic -lxml2 -lalib2std -lalib2data -lalib2algo -lalib2elgo -Wl,-rpath,.
+
+LDFLAGS_RELEASE:=-L../alib2std/lib-release -L../alib2data/lib-release -L../alib2algo/lib-release -L../alib2elgo/lib-release -rdynamic -lxml2 -lalib2std -lalib2data -lalib2algo -lalib2elgo -Wl,-rpath,.
+
+OBJECTS_DEBUG:=$(patsubst src/%.cpp, obj-debug/%.o, $(shell find src/ -name *cpp))
+
+OBJECTS_RELEASE:=$(patsubst src/%.cpp, obj-release/%.o, $(shell find src/ -name *cpp))
+
+.PHONY: all build-debug clean-debug doc
+
+all:
+	@echo "What to do master?"
+
+obj%/makefile: makefile
+	mkdir -p $(dir $@)
+	echo "\
+	SHELL:=/bin/bash$${NEW_LINE}\
+	SRCDIR:=$${NEW_LINE}\
+	DEPTH:=$${NEW_LINE}\
+	OBJECTS_BASE_DIR:=$${NEW_LINE}\
+	$${NEW_LINE}\
+	define NEW_LINE$${NEW_LINE}\
+	$${NEW_LINE}\
+	$${NEW_LINE}\
+	endef$${NEW_LINE}\
+	$${NEW_LINE}\
+	export NEW_LINE$${NEW_LINE}\
+	$${NEW_LINE}\
+	CXXFLAGS:= -std=c++11 \$$(CXX_OTHER_FLAGS) -c -Wall -pedantic -Wextra -Werror -fPIC -I/usr/include/libxml2/ -I../../\$$(DEPTH)alib2std/src -I../../\$$(DEPTH)alib2data/src/ -I../../\$$(DEPTH)alib2algo/src/ -I../../\$$(DEPTH)alib2elgo/src/$${NEW_LINE}\
+	$${NEW_LINE}\
+	SOURCES:= \$$(shell find ../\$$(DEPTH)\$$(SOURCES_BASE_DIR)/\$$(SRCDIR) -maxdepth 1 -type f -name \"*.cpp\")$${NEW_LINE}\
+	DEPENDENCIES:= \$$(patsubst ../\$$(DEPTH)\$$(SOURCES_BASE_DIR)/\$$(SRCDIR)%.cpp, ../\$$(DEPTH)\$$(OBJECTS_BASE_DIR)/\$$(SRCDIR)%.d, \$$(SOURCES))$${NEW_LINE}\
+	OBJECTS:= \$$(patsubst %.d, %.o, \$$(DEPENDENCIES))$${NEW_LINE}\
+	SOURCES_DIRS:= \$$(shell find ../\$$(DEPTH)\$$(SOURCES_BASE_DIR)/\$$(SRCDIR) -maxdepth 1 -mindepth 1 -type d)$${NEW_LINE}\
+	OBJECTS_DIRS:= \$$(patsubst ../\$$(DEPTH)\$$(SOURCES_BASE_DIR)/\$$(SRCDIR)%, %/, \$$(SOURCES_DIRS))$${NEW_LINE}\
+	OBJECTS_DIRS_MAKEFILES:= \$$(patsubst %, %makefile, \$$(OBJECTS_DIRS))$${NEW_LINE}\
+	$${NEW_LINE}\
+	.PHONY: all$${NEW_LINE}\
+	.PRECIOUS: \$$(DEPENDECIES) \$$(OBJECTS_DIRS_MAKEFILES)$${NEW_LINE}\
+	$${NEW_LINE}\
+	all: \$$(OBJECTS_DIRS) \$$(OBJECTS)$${NEW_LINE}\
+	$${NEW_LINE}\
+	%.d: makefile$${NEW_LINE}\
+		@echo \"\\$${NEW_LINE}\
+		\$$(shell sha1sum <<< \"\$$@\" | sed \"s/  -//g\") = \\$$\$$(shell (\\$$\$$(CXX) -MM \\$$\$$(CXXFLAGS) \$$(patsubst ../\$$(DEPTH)\$$(OBJECTS_BASE_DIR)/\$$(SRCDIR)%.d,../\$$(DEPTH)\$$(SOURCES_BASE_DIR)/\$$(SRCDIR)%.cpp, \$$@) 2>/dev/null || echo \\\"\$$(patsubst ../\$$(DEPTH)\$$(OBJECTS_BASE_DIR)/\$$(SRCDIR)%.d,../\$$(DEPTH)\$$(SOURCES_BASE_DIR)/\$$(SRCDIR)%.cpp, \$$@) FORCE\\\") | sed \\\"s/.*://g;s/\\\\\\\\\\\\\\\\//g\\\")\$$\$${NEW_LINE}\\$${NEW_LINE}\
+		\$$(patsubst %.d,%.o, \$$@): \\$$\$$(\$$(shell sha1sum <<< \"\$$@\" | sed \"s/  -//g\")) makefile\$$\$${NEW_LINE}\\$${NEW_LINE}\
+			\\$$\$$(CXX) \\$$\$$(CXXFLAGS) \\$$\$$< -o \$$(patsubst %.d,%.o, \$$@)\$$\$${NEW_LINE}\\$${NEW_LINE}\
+		\" > \$$@$${NEW_LINE}\
+	$${NEW_LINE}\
+	%/makefile: makefile$${NEW_LINE}\
+		mkdir -p \$$(dir \$$@)$${NEW_LINE}\
+		cp makefile \$$@$${NEW_LINE}\
+	$${NEW_LINE}\
+	%/: FORCE | %/makefile$${NEW_LINE}\
+		@accesstime=\`stat -c %Y \$$@\` && \\$${NEW_LINE}\
+		\$$(MAKE) -C \$$@ SRCDIR=\$$(SRCDIR)\$$(notdir \$$(patsubst %/, %, \$$@))/ DEPTH=\$$(DEPTH)../ OBJECTS_BASE_DIR=\$$(OBJECTS_BASE_DIR) SOURCES_BASE_DIR=\$$(SOURCES_BASE_DIR) CXX_OTHER_FLAGS=\"\$$(CXX_OTHER_FLAGS)\" && \\$${NEW_LINE}\
+		accesstime2=\`stat -c %Y \$$@\` && \\$${NEW_LINE}\
+		if [ "\$$\$$accesstime" -ne "\$$\$$accesstime2" ]; then \\$${NEW_LINE}\
+			touch .; \\$${NEW_LINE}\
+		fi$${NEW_LINE}\
+	$${NEW_LINE}\
+	FORCE:$${NEW_LINE}\
+	$${NEW_LINE}\
+	-include \$$(DEPENDENCIES)" > $@
+
+debug: build-debug
+
+release: build-release
+
+clean: clean-debug clean-release
+	$(RM) -r doc
+
+
+
+bin-debug/$(EXECUTABLE): obj-debug/ $(OBJECTS_DEBUG)
+	mkdir -p $(dir $@)
+	$(CXX) $(OBJECTS_DEBUG) -o $@ $(LDFLAGS_DEBUG)
+
+bin-release/$(EXECUTABLE): obj-release/ $(OBJECTS_RELEASE)
+	mkdir -p $(dir $@)
+	$(CXX) $(OBJECTS_RELEASE) -o $@ $(LDFLAGS_RELEASE)
+
+
+
+obj-debug/: FORCE | obj-debug/makefile
+	$(MAKE) -C $@ OBJECTS_BASE_DIR=obj-debug SOURCES_BASE_DIR=src CXX_OTHER_FLAGS="-g -O0"
+
+obj-release/: FORCE | obj-release/makefile
+	$(MAKE) -C $@ OBJECTS_BASE_DIR=obj-release SOURCES_BASE_DIR=src CXX_OTHER_FLAGS="-O3"
+
+
+
+$(OBJECTS_DEBUG): obj-debug/
+
+$(OBJECTS_RELEASE): obj-release/
+
+
+build-debug: bin-debug/$(EXECUTABLE)
+
+build-release: bin-release/$(EXECUTABLE)
+
+
+
+clean-debug:
+	$(RM) -r *.o *.d bin-debug obj-debug
+
+clean-release:
+	$(RM) -r *.o *.d bin-release obj-release
+
+
+
+FORCE:
+
+
+
+doc:
+	doxygen
+
diff --git a/tniceprint/src/tniceprint.cpp b/tniceprint/src/tniceprint.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ec7abbd882a54a75faad9dcd0bd26b74d463ad56
--- /dev/null
+++ b/tniceprint/src/tniceprint.cpp
@@ -0,0 +1,58 @@
+/*
+ * acat.cpp
+ *
+ *  Created on: 24. 2. 2014
+ *      Author: Martin Zak
+ */
+
+#include <tclap/CmdLine.h>
+#include <string>
+#include <exception/AlibException.h>
+#include <factory/XmlDataFactory.hpp>
+#include <sax/SaxParseInterface.h>
+#include <sax/ParserException.h>
+#include <tree/Tree.h>
+
+int main(int argc, char** argv) {
+	try {
+		TCLAP::CmdLine cmd("Tree nice print binary", ' ', "0.01");
+
+		TCLAP::ValueArg<std::string> input(	"i",	"input",	"Input to nice print",		false,	"-",		"file");
+		cmd.add( input );
+
+		cmd.parse(argc, argv);
+
+		std::deque<sax::Token> tokens;
+		if(input.isSet()) {
+			if(input.getValue() == "-") {
+				sax::SaxParseInterface::parseStdin(tokens);
+			} else {
+				sax::SaxParseInterface::parseFile(input.getValue(), tokens);
+			}
+		} else {
+			sax::SaxParseInterface::parseStdin(tokens);
+		}
+
+		if (alib::XmlDataFactory::first<tree::RankedTree>(tokens)) {
+			const tree::RankedTree & tree = alib::XmlDataFactory::fromTokens<tree::RankedTree>(tokens);
+			tree.nicePrint();
+		} else if (alib::XmlDataFactory::first<tree::UnrankedTree>(tokens)) {
+			const tree::UnrankedTree & tree = alib::XmlDataFactory::fromTokens<tree::UnrankedTree>(tokens);
+			tree.nicePrint();
+		} else throw exception::AlibException("no tree on input");
+
+		return 0;
+	} catch(const exception::AlibException& exception) {
+		alib::XmlDataFactory::toStdout(exception);
+		return 1;
+	} catch(const TCLAP::ArgException& exception) {
+		std::cerr << exception.error() << std::endl;
+		return 2;
+	} catch (const std::exception& exception) {
+		std::cerr << "Exception caught: " << exception.what() << std::endl;
+		return 3;
+	} catch(...) {
+		std::cerr << "Unknown exception caught." << std::endl;
+		return 127;
+	}
+}