diff --git a/alib2algo/src/automaton/transform/AutomatonIteration.cpp b/alib2algo/src/automaton/transform/AutomatonIteration.cpp
index b298142286c9d6eccdaaae4c109f8305aac8e2e3..c079d65a95b789a84b9011c81a6925587e0064ab 100644
--- a/alib2algo/src/automaton/transform/AutomatonIteration.cpp
+++ b/alib2algo/src/automaton/transform/AutomatonIteration.cpp
@@ -16,45 +16,7 @@ automaton::Automaton AutomatonIteration::iteration(const automaton::Automaton& a
 	return dispatch(automaton.getData());
 }
 
-automaton::NFA < > AutomatonIteration::iteration(const automaton::DFA < > & automaton) {
-	automaton::NFA < > res(automaton);
-
-	for(const auto& qf : res.getFinalStates())
-		for(const auto& t : res.getTransitionsToState(qf))
-			res.addTransition(t.first.first, t.first.second, res.getInitialState());
-
-	label::Label newInitialState = common::createUnique(automaton.getInitialState(), automaton.getStates());
-	res.addState(newInitialState);
-	res.setInitialState(newInitialState);
-	res.addFinalState(newInitialState);
-
-	for(const auto& t : automaton.getTransitionsFromState(automaton.getInitialState()))
-		res.addTransition(newInitialState, t.first.second, t.second);
-
-	return res;
-}
-
 auto AutomatonIterationDFA = AutomatonIteration::RegistratorWrapper < automaton::NFA < >, automaton::DFA < > > ( AutomatonIteration::iteration );
-
-automaton::NFA < > AutomatonIteration::iteration(const automaton::NFA < > & automaton) {
-	automaton::NFA < > res(automaton);
-
-	for(const auto& qf : res.getFinalStates())
-		for(const auto& t : res.getTransitionsToState(qf))
-			res.addTransition(t.first.first, t.first.second, res.getInitialState());
-
-	label::Label newInitialState = common::createUnique(automaton.getInitialState(), automaton.getStates());
-	res.addState(newInitialState);
-	res.setInitialState(newInitialState);
-	res.addFinalState(newInitialState);
-
-	for(const auto& t : automaton.getTransitionsFromState(automaton.getInitialState()))
-		for (const label::Label & toState : t.second )
-			res.addTransition(newInitialState, t.first.second, toState);
-
-	return res;
-}
-
 auto AutomatonIterationNFA = AutomatonIteration::RegistratorWrapper < automaton::NFA < >, automaton::NFA < > > (AutomatonIteration::iteration);
 
 } /* namespace transform */
diff --git a/alib2algo/src/automaton/transform/AutomatonIteration.h b/alib2algo/src/automaton/transform/AutomatonIteration.h
index e05ef2e1f639ebf04367a192e617352416c9663d..813ad6aadb3f0a1d2550e5e5da4ed7f5f2658831 100644
--- a/alib2algo/src/automaton/transform/AutomatonIteration.h
+++ b/alib2algo/src/automaton/transform/AutomatonIteration.h
@@ -24,10 +24,51 @@ class AutomatonIteration : public std::SingleDispatch<AutomatonIteration, automa
 public:
 	static automaton::Automaton iteration(const automaton::Automaton& automaton);
 
-	static automaton::NFA < > iteration(const automaton::DFA < > & automaton);
-	static automaton::NFA < > iteration(const automaton::NFA < > & automaton);
+	template < class SymbolType, class StateType >
+	static automaton::NFA < SymbolType, StateType > iteration(const automaton::DFA < SymbolType, StateType > & automaton);
+	template < class SymbolType, class StateType >
+	static automaton::NFA < SymbolType, StateType > iteration(const automaton::NFA < SymbolType, StateType > & automaton);
 };
 
+template < class SymbolType, class StateType >
+automaton::NFA < SymbolType, StateType > AutomatonIteration::iteration(const automaton::DFA < SymbolType, StateType > & automaton) {
+	automaton::NFA < SymbolType, StateType > res(automaton);
+
+	for(const auto& qf : res.getFinalStates())
+		for(const auto& t : res.getTransitionsToState(qf))
+			res.addTransition(t.first.first, t.first.second, res.getInitialState());
+
+	StateType newInitialState = common::createUnique(automaton.getInitialState(), automaton.getStates());
+	res.addState(newInitialState);
+	res.setInitialState(newInitialState);
+	res.addFinalState(newInitialState);
+
+	for(const auto& t : automaton.getTransitionsFromState(automaton.getInitialState()))
+		res.addTransition(newInitialState, t.first.second, t.second);
+
+	return res;
+}
+
+template < class SymbolType, class StateType >
+automaton::NFA < SymbolType, StateType > AutomatonIteration::iteration(const automaton::NFA < SymbolType, StateType > & automaton) {
+	automaton::NFA < SymbolType, StateType > res(automaton);
+
+	for(const auto& qf : res.getFinalStates())
+		for(const auto& t : res.getTransitionsToState(qf))
+			res.addTransition(t.first.first, t.first.second, res.getInitialState());
+
+	StateType newInitialState = common::createUnique(automaton.getInitialState(), automaton.getStates());
+	res.addState(newInitialState);
+	res.setInitialState(newInitialState);
+	res.addFinalState(newInitialState);
+
+	for(const auto& t : automaton.getTransitionsFromState(automaton.getInitialState()))
+		for (const label::Label & toState : t.second )
+			res.addTransition(newInitialState, t.first.second, toState);
+
+	return res;
+}
+
 } /* namespace transform */
 
 } /* namespace automaton */
diff --git a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
index c0a49d1f1bdd4e06819fa010cf601ef8f22882c9..67d92430aec788a503b8a11116d334d2d1a5d26f 100644
--- a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
+++ b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
@@ -16,23 +16,7 @@ automaton::Automaton AutomatonIterationEpsilonTransition::iteration(const automa
 	return dispatch(automaton.getData());
 }
 
-template<class T>
-automaton::EpsilonNFA < > AutomatonIterationEpsilonTransition::iteration(const T& automaton) {
-	automaton::EpsilonNFA < > res(automaton);
-
-	for(const auto&q : automaton.getFinalStates())
-		res.addTransition(q, automaton.getInitialState());
-
-	label::Label newInitialState = common::createUnique(automaton.getInitialState(), automaton.getStates());
-	res.addState(newInitialState);
-	res.setInitialState(newInitialState);
-	res.addFinalState(newInitialState);
-
-	res.addTransition(newInitialState, automaton.getInitialState());
-	return res;
-}
-
-auto AutomatonIterationEpsilonTransitionDFA = AutomatonIterationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::DFA<>>(AutomatonIterationEpsilonTransition::iteration);
+auto AutomatonIterationEpsilonTransitionDFA = AutomatonIterationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::DFA < > >(AutomatonIterationEpsilonTransition::iteration);
 auto AutomatonIterationEpsilonTransitionNFA = AutomatonIterationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::NFA < > >(AutomatonIterationEpsilonTransition::iteration);
 auto AutomatonIterationEpsilonTransitionEpsilonNFA = AutomatonIterationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::EpsilonNFA < > >(AutomatonIterationEpsilonTransition::iteration);
 
diff --git a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h
index adfe609d41815c9ebfdee346f29e5fae9511467f..7615e25e1e23797041141c15f53ae94f37e7278c 100644
--- a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h
+++ b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h
@@ -24,10 +24,26 @@ class AutomatonIterationEpsilonTransition : public std::SingleDispatch<Automaton
 public:
 	static automaton::Automaton iteration(const automaton::Automaton& automaton);
 
-	template<class T>
-	static automaton::EpsilonNFA < > iteration(const T& automaton);
+	template < class T, class SymbolType = typename automaton::SymbolTypeOfAutomaton < T >, class EpsilonType = DefaultEpsilonType, class StateType = typename automaton::StateTypeOfAutomaton < T > >
+	static automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > iteration(const T& automaton);
 };
 
+template < class T, class SymbolType, class EpsilonType, class StateType >
+automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > AutomatonIterationEpsilonTransition::iteration(const T& automaton) {
+	automaton::EpsilonNFA < > res(automaton);
+
+	for(const auto&q : automaton.getFinalStates())
+		res.addTransition(q, automaton.getInitialState());
+
+	StateType newInitialState = common::createUnique(automaton.getInitialState(), automaton.getStates());
+	res.addState(newInitialState);
+	res.setInitialState(newInitialState);
+	res.addFinalState(newInitialState);
+
+	res.addTransition(newInitialState, automaton.getInitialState());
+	return res;
+}
+
 } /* namespace transform */
 
 } /* namespace automaton */
diff --git a/alib2algo/src/automaton/transform/Compaction.cpp b/alib2algo/src/automaton/transform/Compaction.cpp
index 43417fa743f07f396464360297a274c39cdb9a92..32e58355f55b98738395cc6569dcb63e5a1efb50 100644
--- a/alib2algo/src/automaton/transform/Compaction.cpp
+++ b/alib2algo/src/automaton/transform/Compaction.cpp
@@ -7,12 +7,6 @@
 
 #include "Compaction.h"
 
-#include <automaton/FSM/CompactNFA.h>
-#include <automaton/FSM/DFA.h>
-
-#include <stack>
-#include <tuple>
-
 namespace automaton {
 
 namespace transform {
@@ -21,66 +15,8 @@ automaton::Automaton Compaction::convert(const automaton::Automaton& automaton)
 	return dispatch(automaton.getData());
 }
 
-automaton::CompactNFA < > Compaction::convert(const automaton::CompactNFA < > & automaton) {
-	return automaton;
-}
-
 auto CompactionCompactNFA = Compaction::RegistratorWrapper<automaton::CompactNFA < >, automaton::CompactNFA < > >(Compaction::convert);
-
-automaton::CompactNFA < > Compaction::convert(const automaton::DFA<>& automaton) {
-	automaton::CompactNFA < > res(automaton.getInitialState());
-	res.setInputAlphabet(automaton.getInputAlphabet());
-
-	std::set<label::Label> visited;
-
-	std::stack<std::tuple<label::Label, label::Label, alphabet::Symbol>> stack; // state x lastFork x symbol we used to go to that state
-	for(const auto& transition: automaton.getTransitionsFromState(automaton.getInitialState()))
-		stack.push(std::make_tuple(transition.second, automaton.getInitialState(), transition.first.second));
-
-	if(automaton.getFinalStates().count(automaton.getInitialState()) > 0)
-		res.addFinalState(automaton.getInitialState());
-
-	while(!stack.empty()) {
-		label::Label q = std::move(std::get<0>(stack.top()));
-		label::Label lastFork = std::move(std::get<1>(stack.top()));
-		alphabet::Symbol symbol = std::move(std::get<2>(stack.top()));
-		stack.pop();
-
-		std::vector < alphabet::Symbol > path { symbol };
-
-		std::map<std::pair<label::Label, alphabet::Symbol>, label::Label> transitions;
-		// only 1 child and nonfinal
-		while((transitions = automaton.getTransitionsFromState(q)).size() == 1 && automaton.getFinalStates().count(q) == 0) {
-			const std::pair<std::pair<label::Label, alphabet::Symbol>, label::Label>& transition = * transitions.begin();
-			path.push_back(transition.first.second);
-			q = transition.second;
-		}
-
-		// fork or final state
-		res.addState(q);
-
-		if(automaton.getFinalStates().count(q))
-			res.addFinalState(q);
-
-		res.addTransition(lastFork, path, q);
-
-		for(const std::pair<const std::pair<label::Label, alphabet::Symbol>, label::Label>& transition : automaton.getTransitionsFromState(q))
-			if(visited.insert(transition.second).second)
-				stack.push(std::make_tuple(transition.second, q, transition.first.second));
-
-	}
-
-	return res;
-}
-
-auto CompactionDFA = Compaction::RegistratorWrapper<automaton::CompactNFA < >, automaton::DFA<>>(Compaction::convert);
-
-automaton::CompactNFA < > Compaction::convert(const automaton::NFA < > & automaton) {
-	automaton::CompactNFA < > res(automaton.getInitialState());
-	// TODO
-	return res;
-}
-
+auto CompactionDFA = Compaction::RegistratorWrapper<automaton::CompactNFA < >, automaton::DFA < > >(Compaction::convert);
 auto CompactionNFA = Compaction::RegistratorWrapper<automaton::CompactNFA < >, automaton::NFA < > >(Compaction::convert);
 
 } /* namespace transform */
diff --git a/alib2algo/src/automaton/transform/Compaction.h b/alib2algo/src/automaton/transform/Compaction.h
index 76a99b994a4e12e76b12457b43fcaf2ed4f7c148..b9543cc15418de3068ebfe62511c0a6da2bac154 100644
--- a/alib2algo/src/automaton/transform/Compaction.h
+++ b/alib2algo/src/automaton/transform/Compaction.h
@@ -8,9 +8,15 @@
 #ifndef COMPACTION_H_
 #define COMPACTION_H_
 
+#include <stack>
+#include <tuple>
+
 #include <core/multipleDispatch.hpp>
+
 #include "automaton/Automaton.h"
 #include "automaton/AutomatonFeatures.h"
+#include <automaton/FSM/CompactNFA.h>
+#include <automaton/FSM/DFA.h>
 
 namespace automaton {
 
@@ -21,9 +27,12 @@ namespace transform {
  */
 class Compaction : public std::SingleDispatch<Compaction, automaton::Automaton, const automaton::AutomatonBase &> {
 public:
-	static automaton::CompactNFA < > convert( const automaton::DFA<>& automaton);
-	static automaton::CompactNFA < > convert( const automaton::NFA < > & automaton);
-	static automaton::CompactNFA < > convert( const automaton::CompactNFA < > & automaton);
+	template < class SymbolType, class StateType >
+	static automaton::CompactNFA < SymbolType, StateType > convert( const automaton::DFA < SymbolType, StateType > & automaton);
+	template < class SymbolType, class StateType >
+	static automaton::CompactNFA < SymbolType, StateType > convert( const automaton::NFA < SymbolType, StateType > & automaton);
+	template < class SymbolType, class StateType >
+	static automaton::CompactNFA < SymbolType, StateType > convert( const automaton::CompactNFA < SymbolType, StateType > & automaton);
 
 	/**
 	 * Transforms
@@ -33,6 +42,65 @@ public:
 	static automaton::Automaton convert( const automaton::Automaton & automaton );
 };
 
+template < class SymbolType, class StateType >
+automaton::CompactNFA < SymbolType, StateType > Compaction::convert(const automaton::CompactNFA < SymbolType, StateType > & automaton) {
+	return automaton;
+}
+
+template < class SymbolType, class StateType >
+automaton::CompactNFA < SymbolType, StateType > Compaction::convert(const automaton::DFA < SymbolType, StateType > & automaton) {
+	automaton::CompactNFA < SymbolType, StateType > res(automaton.getInitialState());
+	res.setInputAlphabet(automaton.getInputAlphabet());
+
+	std::set<label::Label> visited;
+
+	std::stack<std::tuple<label::Label, label::Label, alphabet::Symbol>> stack; // state x lastFork x symbol we used to go to that state
+	for(const auto& transition: automaton.getTransitionsFromState(automaton.getInitialState()))
+		stack.push(std::make_tuple(transition.second, automaton.getInitialState(), transition.first.second));
+
+	if(automaton.getFinalStates().count(automaton.getInitialState()) > 0)
+		res.addFinalState(automaton.getInitialState());
+
+	while(!stack.empty()) {
+		label::Label q = std::move(std::get<0>(stack.top()));
+		label::Label lastFork = std::move(std::get<1>(stack.top()));
+		alphabet::Symbol symbol = std::move(std::get<2>(stack.top()));
+		stack.pop();
+
+		std::vector < alphabet::Symbol > path { symbol };
+
+		std::map<std::pair<label::Label, alphabet::Symbol>, label::Label> transitions;
+		// only 1 child and nonfinal
+		while((transitions = automaton.getTransitionsFromState(q)).size() == 1 && automaton.getFinalStates().count(q) == 0) {
+			const std::pair<std::pair<label::Label, alphabet::Symbol>, label::Label>& transition = * transitions.begin();
+			path.push_back(transition.first.second);
+			q = transition.second;
+		}
+
+		// fork or final state
+		res.addState(q);
+
+		if(automaton.getFinalStates().count(q))
+			res.addFinalState(q);
+
+		res.addTransition(lastFork, path, q);
+
+		for(const std::pair<const std::pair<label::Label, alphabet::Symbol>, label::Label>& transition : automaton.getTransitionsFromState(q))
+			if(visited.insert(transition.second).second)
+				stack.push(std::make_tuple(transition.second, q, transition.first.second));
+
+	}
+
+	return res;
+}
+
+template < class SymbolType, class StateType >
+automaton::CompactNFA < SymbolType, StateType > Compaction::convert(const automaton::NFA < SymbolType, StateType > & automaton) {
+	automaton::CompactNFA < SymbolType, StateType > res(automaton.getInitialState());
+	// TODO
+	return res;
+}
+
 } /* namespace transform */
 
 } /* namespace automaton */