diff --git a/alib2algo/src/automaton/simplify/Minimize.cpp b/alib2algo/src/automaton/simplify/Minimize.cpp
index 8b51f0729dfc291fc0e0f88f2dafa35349e460dc..7cd64184fe8b4d8ec780443c4f0f0226a7c1a378 100644
--- a/alib2algo/src/automaton/simplify/Minimize.cpp
+++ b/alib2algo/src/automaton/simplify/Minimize.cpp
@@ -7,15 +7,6 @@
 
 #include "Minimize.h"
 
-#include <map>
-#include <set>
-#include <iomanip>
-#include <sstream>
-
-#include <alphabet/Symbol.h>
-
-#include <global/GlobalData.h>
-
 namespace automaton {
 
 namespace simplify {
@@ -24,201 +15,6 @@ automaton::Automaton Minimize::minimize(const automaton::Automaton& automaton) {
 	return dispatch(automaton.getData());
 }
 
-automaton::DFA<> Minimize::minimize(const automaton::DFA<>& dfa) {
-	if(dfa.getFinalStates().size() == 0) {
-		automaton::DFA < > result(dfa.getInitialState());
-		result.setInputAlphabet(dfa.getInputAlphabet());
-		return result;
-	}
-
-	std::map<label::Label, std::map<alphabet::Symbol, label::Label > > refactor;
-
-	for(const label::Label& state : dfa.getStates()) {
-		refactor.insert(std::make_pair(state, std::map<alphabet::Symbol, label::Label>()));
-	}
-
-	for(const std::pair<const std::pair<label::Label, alphabet::Symbol>, label::Label>& transition : dfa.getTransitions()) {
-		refactor[transition.first.first].insert(std::make_pair(transition.first.second, transition.second));
-	}
-
-	std::map<label::Label, label::Label> toEquvivalentStates1; //original state to equivalent state
-	std::map<std::pair<label::Label, std::set<std::pair<alphabet::Symbol, label::Label> > >, std::set<label::Label> > minimizedTransitionFunction1; //mapped to the original state
-
-	std::map<label::Label, label::Label> toEquvivalentStates2;
-	std::map<std::pair<label::Label, std::set<std::pair<alphabet::Symbol, label::Label> > >, std::set<label::Label> > minimizedTransitionFunction2;
-
-	const label::Label *firstFinal = NULL, *firstNonfinal = NULL;
-	for(const label::Label& state : dfa.getStates()) {
-		if(dfa.getFinalStates().count(state) == 0) { // not a final state
-			if(!firstNonfinal) firstNonfinal = &state;
-			toEquvivalentStates2.insert(std::pair<label::Label, label::Label>(state, *firstNonfinal));
-		} else {
-			if(!firstFinal) firstFinal = &state;
-			toEquvivalentStates2.insert(std::pair<label::Label, label::Label>(state, *firstFinal));
-		}
-	}
-
-	for(const std::pair<const label::Label, std::map<alphabet::Symbol, label::Label> >& transition : refactor) {
-		const label::Label& from = toEquvivalentStates2.find(transition.first)->second;
-		std::set<std::pair<alphabet::Symbol, label::Label> > transitionFunction;
-
-		for(const std::pair<const alphabet::Symbol, label::Label> & transitionFromState : transition.second) {
-			transitionFunction.insert(std::make_pair(transitionFromState.first, toEquvivalentStates2.find(transitionFromState.second)->second));
-		}
-
-		minimizedTransitionFunction2[std::make_pair(from, transitionFunction)].insert(transition.first);
-	}
-
-	size_t delta_iter = 0;
-	if(common::GlobalData::verbose) {
-		print_progress(dfa, minimizedTransitionFunction2, delta_iter++);
-	}
-
-	do {
-		toEquvivalentStates1 = toEquvivalentStates2;
-		minimizedTransitionFunction1 = minimizedTransitionFunction2;
-
-		toEquvivalentStates2.clear();
-		minimizedTransitionFunction2.clear();
-
-		for(const std::pair<const std::pair<label::Label, std::set<std::pair<alphabet::Symbol, label::Label> > >, std::set<label::Label> >& transition : minimizedTransitionFunction1) {
-			for(const label::Label& target : transition.second) {
-				toEquvivalentStates2.insert(std::make_pair(target, *(transition.second.begin())));
-			}
-		}
-
-		for(const std::pair<const label::Label, std::map<alphabet::Symbol, label::Label> >& transition : refactor) {
-			const label::Label& from = toEquvivalentStates2.find(transition.first)->second;
-			std::set<std::pair<alphabet::Symbol, label::Label> > transitionFunction;
-
-			for(const std::pair<const alphabet::Symbol, label::Label> & transitionFromState : transition.second) {
-				transitionFunction.insert(std::make_pair(transitionFromState.first, toEquvivalentStates2.find(transitionFromState.second)->second));
-			}
-
-			minimizedTransitionFunction2[std::make_pair(from, transitionFunction)].insert(transition.first);
-		}
-
-		if(common::GlobalData::verbose) {
-			print_progress(dfa, minimizedTransitionFunction2, delta_iter++);
-		}
-
-	} while(minimizedTransitionFunction1.size() != minimizedTransitionFunction2.size());
-
-	const label::Label* initialState = NULL;
-	for(const std::pair<const std::pair<label::Label, std::set<std::pair<alphabet::Symbol, label::Label> > >, std::set<label::Label> >& transition : minimizedTransitionFunction2) {
-		if(transition.second.count(dfa.getInitialState())) {
-			initialState = &(transition.first.first);
-			break;
-		}
-	}
-
-	automaton::DFA<> result(*initialState);
-
-	result.setInputAlphabet(dfa.getInputAlphabet());
-
-	for(const std::pair<const std::pair<label::Label, std::set<std::pair<alphabet::Symbol, label::Label> > >, std::set<label::Label> >& transition : minimizedTransitionFunction2) {
-		result.addState(transition.first.first);
-		if(dfa.getFinalStates().count(*(transition.second.begin()))) {
-			result.addFinalState(transition.first.first);
-		}
-	}
-
-	for(const std::pair<const std::pair<label::Label, std::set<std::pair<alphabet::Symbol, label::Label> > >, std::set<label::Label> >& transition : minimizedTransitionFunction2) {
-		for(const std::pair<alphabet::Symbol, label::Label>& transitionFromState : transition.first.second) {
-			result.addTransition(transition.first.first, transitionFromState.first, transitionFromState.second);
-		}
-	}
-
-	return result;
-}
-
-#define RESETSS(x) {(x).clear(); (x).str("");}
-
-void Minimize::print_progress(const automaton::DFA<>& dfa, const std::map<std::pair<label::Label, std::set<std::pair<alphabet::Symbol, label::Label> > >, std::set<label::Label> >& minimizedTransitionFunction, size_t iter) {
-	std::clog << "delta " << iter << std::endl;
-
-	//std::map<std::pair<label::Label, std::set<std::pair<alphabet::Symbol, label::Label> > >, std::set<label::Label> > minimizedTransitionFunction1; //mapped to the original state
-
-	/* need to restruct this first so we have table like:	orig state | new state | trans_symb_1 | trans_symb_2 | ... | trans_symb_n */
-	// we surely have DFA here (transition map hence)
-	std::map<std::pair<label::Label, label::Label>, std::map<alphabet::Symbol, label::Label>> printMap;
-	for(const auto& kv: minimizedTransitionFunction) {
-		for(const auto& state : kv.second) {
-			std::map<alphabet::Symbol, label::Label> stateTransMap;
-			for(const auto& transition : kv.first.second) {
-				stateTransMap.insert(std::make_pair(transition.first, transition.second));
-			}
-			printMap.insert(std::make_pair(std::make_pair(state, kv.first.first), stateTransMap));
-		}
-	}
-
-	size_t stateWidth = 1, stateMapWidth = 1;
-	std::map<alphabet::Symbol, size_t> colWidths;
-	std::ostringstream ss;
-
-	for(const alphabet::Symbol& symbol : dfa.getInputAlphabet()) {
-		ss << symbol;
-		colWidths[symbol] = ss.str().size();
-		RESETSS(ss);
-	}
-	for(const auto& kv : printMap) {
-		ss << kv.first.first;
-		stateWidth = std::max(stateWidth, ss.str().size());
-		RESETSS(ss);
-
-		ss << kv.first.second;
-		stateMapWidth = std::max(stateMapWidth, ss.str().size());
-		RESETSS(ss);
-
-		for(const alphabet::Symbol& symbol : dfa.getInputAlphabet()) {
-			auto it = kv.second.find(symbol);
-			if(it != kv.second.end())
-			{
-				ss << it -> second;
-				colWidths[symbol] = std::max(colWidths[symbol], ss.str().size());
-				RESETSS(ss);
-			}
-		}
-	}
-
-	std::clog << std::setw(stateWidth) << "";
-	std::clog << " | ";
-	std::clog << std::setw(stateMapWidth) << "";
-	std::clog << " | ";
-	for(const alphabet::Symbol& symbol : dfa.getInputAlphabet()) {
-		ss << symbol;
-		std::clog << std::setw(colWidths[symbol]) << ss.str() << " | ";
-		RESETSS(ss);
-	}
-	std::clog << std::endl;
-	for(const auto& kv : printMap) {
-		ss << kv.first.first;
-		std::clog << std::setw(stateWidth) << ss.str() << " | ";
-		RESETSS(ss);
-
-		ss << kv.first.second;
-		std::clog << std::setw(stateMapWidth) << ss.str() << " | ";
-		RESETSS(ss);
-
-		for(const auto& symbol : dfa.getInputAlphabet()) {
-			auto it = kv.second.find(symbol);
-			if(it != kv.second.end())
-			{
-				ss << it -> second;
-				std::clog << std::setw(colWidths[symbol]) << ss.str();
-				RESETSS(ss);
-			}
-			else
-			{
-				std::clog << std::setw(colWidths[symbol]) << "";
-			}
-			std::clog << " | ";
-		}
-		std::clog << std::endl;
-	}
-	std::clog << std::endl;
-}
-
 auto MinimizeNFA = Minimize::RegistratorWrapper<automaton::DFA<>, automaton::DFA<>>( Minimize::minimize );
 
 } /* namespace simplify */
diff --git a/alib2algo/src/automaton/simplify/Minimize.h b/alib2algo/src/automaton/simplify/Minimize.h
index 11e0d876cb8861507264f39887e54214c6448309..41dde5759a5faf1cf4e6218f39a9b218dc1484ff 100644
--- a/alib2algo/src/automaton/simplify/Minimize.h
+++ b/alib2algo/src/automaton/simplify/Minimize.h
@@ -12,6 +12,13 @@
 #include <automaton/Automaton.h>
 #include <automaton/FSM/DFA.h>
 
+#include <map>
+#include <set>
+#include <iomanip>
+#include <sstream>
+
+#include <global/GlobalData.h>
+
 namespace automaton {
 
 namespace simplify {
@@ -23,12 +30,208 @@ public:
 	 */
 	static automaton::Automaton minimize(const automaton::Automaton& dfa);
 
-	static automaton::DFA<> minimize(const automaton::DFA<>& dfa);
+	template < class SymbolType, class StateType >
+	static automaton::DFA < SymbolType, StateType > minimize(const automaton::DFA < SymbolType, StateType >& dfa);
 
 private:
-	static void print_progress(const automaton::DFA<>& dfa, const std::map<std::pair<label::Label, std::set<std::pair<alphabet::Symbol, label::Label> > >, std::set<label::Label> >& minimizedTransitionFunction, size_t iter);
+	template < class SymbolType, class StateType >
+	static void print_progress(const automaton::DFA < SymbolType, StateType >& dfa, const std::map<std::pair<StateType, std::set<std::pair<SymbolType, StateType> > >, std::set<StateType> >& minimizedTransitionFunction, size_t iter);
 };
 
+template < class SymbolType, class StateType >
+automaton::DFA < SymbolType, StateType > Minimize::minimize(const automaton::DFA < SymbolType, StateType >& dfa) {
+	if(dfa.getFinalStates().size() == 0) {
+		automaton::DFA < SymbolType, StateType > result(dfa.getInitialState());
+		result.setInputAlphabet(dfa.getInputAlphabet());
+		return result;
+	}
+
+	std::map<StateType, std::map<SymbolType, StateType > > refactor;
+
+	for(const StateType& state : dfa.getStates()) {
+		refactor.insert(std::make_pair(state, std::map<SymbolType, StateType>()));
+	}
+
+	for(const std::pair<const std::pair<StateType, SymbolType>, StateType>& transition : dfa.getTransitions()) {
+		refactor[transition.first.first].insert(std::make_pair(transition.first.second, transition.second));
+	}
+
+	std::map<StateType, StateType> toEquvivalentStates1; //original state to equivalent state
+	std::map<std::pair<StateType, std::set<std::pair<SymbolType, StateType> > >, std::set<StateType> > minimizedTransitionFunction1; //mapped to the original state
+
+	std::map<StateType, StateType> toEquvivalentStates2;
+	std::map<std::pair<StateType, std::set<std::pair<SymbolType, StateType> > >, std::set<StateType> > minimizedTransitionFunction2;
+
+	const StateType *firstFinal = NULL, *firstNonfinal = NULL;
+	for(const StateType& state : dfa.getStates()) {
+		if(dfa.getFinalStates().count(state) == 0) { // not a final state
+			if(!firstNonfinal) firstNonfinal = &state;
+			toEquvivalentStates2.insert(std::pair<StateType, StateType>(state, *firstNonfinal));
+		} else {
+			if(!firstFinal) firstFinal = &state;
+			toEquvivalentStates2.insert(std::pair<StateType, StateType>(state, *firstFinal));
+		}
+	}
+
+	for(const std::pair<const StateType, std::map<SymbolType, StateType> >& transition : refactor) {
+		const StateType& from = toEquvivalentStates2.find(transition.first)->second;
+		std::set<std::pair<SymbolType, StateType> > transitionFunction;
+
+		for(const std::pair<const SymbolType, StateType> & transitionFromState : transition.second) {
+			transitionFunction.insert(std::make_pair(transitionFromState.first, toEquvivalentStates2.find(transitionFromState.second)->second));
+		}
+
+		minimizedTransitionFunction2[std::make_pair(from, transitionFunction)].insert(transition.first);
+	}
+
+	size_t delta_iter = 0;
+	if(common::GlobalData::verbose) {
+		print_progress(dfa, minimizedTransitionFunction2, delta_iter++);
+	}
+
+	do {
+		toEquvivalentStates1 = toEquvivalentStates2;
+		minimizedTransitionFunction1 = minimizedTransitionFunction2;
+
+		toEquvivalentStates2.clear();
+		minimizedTransitionFunction2.clear();
+
+		for(const std::pair<const std::pair<StateType, std::set<std::pair<SymbolType, StateType> > >, std::set<StateType> >& transition : minimizedTransitionFunction1) {
+			for(const StateType& target : transition.second) {
+				toEquvivalentStates2.insert(std::make_pair(target, *(transition.second.begin())));
+			}
+		}
+
+		for(const std::pair<const StateType, std::map<SymbolType, StateType> >& transition : refactor) {
+			const StateType& from = toEquvivalentStates2.find(transition.first)->second;
+			std::set<std::pair<SymbolType, StateType> > transitionFunction;
+
+			for(const std::pair<const SymbolType, StateType> & transitionFromState : transition.second) {
+				transitionFunction.insert(std::make_pair(transitionFromState.first, toEquvivalentStates2.find(transitionFromState.second)->second));
+			}
+
+			minimizedTransitionFunction2[std::make_pair(from, transitionFunction)].insert(transition.first);
+		}
+
+		if(common::GlobalData::verbose) {
+			print_progress(dfa, minimizedTransitionFunction2, delta_iter++);
+		}
+
+	} while(minimizedTransitionFunction1.size() != minimizedTransitionFunction2.size());
+
+	const StateType* initialState = NULL;
+	for(const std::pair<const std::pair<StateType, std::set<std::pair<SymbolType, StateType> > >, std::set<StateType> >& transition : minimizedTransitionFunction2) {
+		if(transition.second.count(dfa.getInitialState())) {
+			initialState = &(transition.first.first);
+			break;
+		}
+	}
+
+	automaton::DFA < SymbolType, StateType > result(*initialState);
+
+	result.setInputAlphabet(dfa.getInputAlphabet());
+
+	for(const std::pair<const std::pair<StateType, std::set<std::pair<SymbolType, StateType> > >, std::set<StateType> >& transition : minimizedTransitionFunction2) {
+		result.addState(transition.first.first);
+		if(dfa.getFinalStates().count(*(transition.second.begin()))) {
+			result.addFinalState(transition.first.first);
+		}
+	}
+
+	for(const std::pair<const std::pair<StateType, std::set<std::pair<SymbolType, StateType> > >, std::set<StateType> >& transition : minimizedTransitionFunction2) {
+		for(const std::pair<SymbolType, StateType>& transitionFromState : transition.first.second) {
+			result.addTransition(transition.first.first, transitionFromState.first, transitionFromState.second);
+		}
+	}
+
+	return result;
+}
+
+#define RESETSS(x) {(x).clear(); (x).str("");}
+
+template < class SymbolType, class StateType >
+void Minimize::print_progress(const automaton::DFA < SymbolType, StateType >& dfa, const std::map<std::pair<StateType, std::set<std::pair<SymbolType, StateType> > >, std::set<StateType> >& minimizedTransitionFunction, size_t iter) {
+	std::clog << "delta " << iter << std::endl;
+
+	//std::map<std::pair<StateType, std::set<std::pair<SymbolType, StateType> > >, std::set<StateType> > minimizedTransitionFunction1; //mapped to the original state
+
+	/* need to restruct this first so we have table like:	orig state | new state | trans_symb_1 | trans_symb_2 | ... | trans_symb_n */
+	// we surely have DFA here (transition map hence)
+	std::map<std::pair<StateType, StateType>, std::map<SymbolType, StateType>> printMap;
+	for(const auto& kv: minimizedTransitionFunction) {
+		for(const auto& state : kv.second) {
+			std::map<SymbolType, StateType> stateTransMap;
+			for(const auto& transition : kv.first.second) {
+				stateTransMap.insert(std::make_pair(transition.first, transition.second));
+			}
+			printMap.insert(std::make_pair(std::make_pair(state, kv.first.first), stateTransMap));
+		}
+	}
+
+	size_t stateWidth = 1, stateMapWidth = 1;
+	std::map<SymbolType, size_t> colWidths;
+	std::ostringstream ss;
+
+	for(const SymbolType& symbol : dfa.getInputAlphabet()) {
+		ss << symbol;
+		colWidths[symbol] = ss.str().size();
+		RESETSS(ss);
+	}
+	for(const auto& kv : printMap) {
+		ss << kv.first.first;
+		stateWidth = std::max(stateWidth, ss.str().size());
+		RESETSS(ss);
+
+		ss << kv.first.second;
+		stateMapWidth = std::max(stateMapWidth, ss.str().size());
+		RESETSS(ss);
+
+		for(const SymbolType& symbol : dfa.getInputAlphabet()) {
+			auto it = kv.second.find(symbol);
+			if(it != kv.second.end()) {
+				ss << it -> second;
+				colWidths[symbol] = std::max(colWidths[symbol], ss.str().size());
+				RESETSS(ss);
+			}
+		}
+	}
+
+	std::clog << std::setw(stateWidth) << "";
+	std::clog << " | ";
+	std::clog << std::setw(stateMapWidth) << "";
+	std::clog << " | ";
+	for(const SymbolType& symbol : dfa.getInputAlphabet()) {
+		ss << symbol;
+		std::clog << std::setw(colWidths[symbol]) << ss.str() << " | ";
+		RESETSS(ss);
+	}
+	std::clog << std::endl;
+	for(const auto& kv : printMap) {
+		ss << kv.first.first;
+		std::clog << std::setw(stateWidth) << ss.str() << " | ";
+		RESETSS(ss);
+
+		ss << kv.first.second;
+		std::clog << std::setw(stateMapWidth) << ss.str() << " | ";
+		RESETSS(ss);
+
+		for(const auto& symbol : dfa.getInputAlphabet()) {
+			auto it = kv.second.find(symbol);
+			if(it != kv.second.end()) {
+				ss << it -> second;
+				std::clog << std::setw(colWidths[symbol]) << ss.str();
+				RESETSS(ss);
+			}
+			else {
+				std::clog << std::setw(colWidths[symbol]) << "";
+			}
+			std::clog << " | ";
+		}
+		std::clog << std::endl;
+	}
+	std::clog << std::endl;
+}
+
 } /* namespace simplify */
 
 } /* namespace automaton */