diff --git a/alib2algo/src/automaton/properties/UnreachableStates.cpp b/alib2algo/src/automaton/properties/ReachableStates.cpp
similarity index 56%
rename from alib2algo/src/automaton/properties/UnreachableStates.cpp
rename to alib2algo/src/automaton/properties/ReachableStates.cpp
index 6e23bae903fa31b72b5f1e670ccb6505ae4435c3..868d0b7a9ac1a3a9657d93f9a39b0de0a4783eac 100644
--- a/alib2algo/src/automaton/properties/UnreachableStates.cpp
+++ b/alib2algo/src/automaton/properties/ReachableStates.cpp
@@ -1,11 +1,11 @@
 /*
- * UnreachableStates.cpp
+ * ReachableStates.cpp
  *
  *  Created on: 23. 3. 2014
  *	  Author: Tomas Pecka
  */
 
-#include "UnreachableStates.h"
+#include "ReachableStates.h"
 
 #include <exception/AlibException.h>
 #include <automaton/FSM/ExtendedNFA.h>
@@ -22,14 +22,14 @@ namespace automaton {
 
 namespace properties {
 
-std::set<automaton::State> UnreachableStates::unreachableStates(const Automaton& automaton) {
+std::set<automaton::State> ReachableStates::reachableStates(const Automaton& automaton) {
 	std::set<automaton::State> out;
-	automaton.getData().Accept((void*) &out, UnreachableStates::UNREACHABLE_STATES);
+	automaton.getData().Accept((void*) &out, ReachableStates::REACHABLE_STATES);
 	return out;
 }
 
 template<class T>
-std::set<automaton::State> UnreachableStates::unreachableStates( const T & fsm ) {
+std::set<automaton::State> ReachableStates::reachableStates( const T & fsm ) {
 	// 1a
 	std::deque<std::set<automaton::State>> Qi;
 	Qi.push_back( std::set<automaton::State>( ) );
@@ -54,13 +54,13 @@ std::set<automaton::State> UnreachableStates::unreachableStates( const T & fsm )
 	return Qi.at( i );
 }
 
-template std::set<automaton::State> UnreachableStates::unreachableStates( const automaton::EpsilonNFA & fsm );
-template std::set<automaton::State> UnreachableStates::unreachableStates( const automaton::NFA & fsm );
-template std::set<automaton::State> UnreachableStates::unreachableStates( const automaton::CompactNFA & fsm );
-template std::set<automaton::State> UnreachableStates::unreachableStates( const automaton::ExtendedNFA & fsm );
+template std::set<automaton::State> ReachableStates::reachableStates( const automaton::EpsilonNFA & fsm );
+template std::set<automaton::State> ReachableStates::reachableStates( const automaton::NFA & fsm );
+template std::set<automaton::State> ReachableStates::reachableStates( const automaton::CompactNFA & fsm );
+template std::set<automaton::State> ReachableStates::reachableStates( const automaton::ExtendedNFA & fsm );
 
 template<>
-std::set<automaton::State> UnreachableStates::unreachableStates( const automaton::MultiInitialStateNFA & fsm ) {
+std::set<automaton::State> ReachableStates::reachableStates( const automaton::MultiInitialStateNFA & fsm ) {
 	// 1a
 	std::deque<std::set<automaton::State>> Qi;
 	Qi.push_back( std::set<automaton::State>( ) );
@@ -86,7 +86,7 @@ std::set<automaton::State> UnreachableStates::unreachableStates( const automaton
 }
 
 template<>
-std::set<automaton::State> UnreachableStates::unreachableStates( const automaton::DFA & fsm ) {
+std::set<automaton::State> ReachableStates::reachableStates( const automaton::DFA & fsm ) {
 	// 1a
 	std::deque<std::set<automaton::State>> Qi;
 	Qi.push_back( std::set<automaton::State>( ) );
@@ -111,81 +111,81 @@ std::set<automaton::State> UnreachableStates::unreachableStates( const automaton
 	return Qi.at( i );
 }
 
-void UnreachableStates::Visit(void* data, const EpsilonNFA& automaton) const {
+void ReachableStates::Visit(void* data, const EpsilonNFA& automaton) const {
 	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
-	out = std::move(this->unreachableStates(automaton));
+	out = std::move(this->reachableStates(automaton));
 }
 
-void UnreachableStates::Visit(void* data, const MultiInitialStateNFA& automaton) const {
+void ReachableStates::Visit(void* data, const MultiInitialStateNFA& automaton) const {
 	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
-	out = std::move(this->unreachableStates(automaton));
+	out = std::move(this->reachableStates(automaton));
 }
 
-void UnreachableStates::Visit(void* data, const NFA& automaton) const {
+void ReachableStates::Visit(void* data, const NFA& automaton) const {
 	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
-	out = std::move(this->unreachableStates(automaton));
+	out = std::move(this->reachableStates(automaton));
 }
 
-void UnreachableStates::Visit(void* data, const DFA& automaton) const {
+void ReachableStates::Visit(void* data, const DFA& automaton) const {
 	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
-	out = std::move(this->unreachableStates(automaton));
+	out = std::move(this->reachableStates(automaton));
 }
 
-void UnreachableStates::Visit(void* data, const ExtendedNFA& automaton) const {
+void ReachableStates::Visit(void* data, const ExtendedNFA& automaton) const {
 	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
-	out = std::move(this->unreachableStates(automaton));
+	out = std::move(this->reachableStates(automaton));
 }
 
-void UnreachableStates::Visit(void* data, const CompactNFA& automaton) const {
+void ReachableStates::Visit(void* data, const CompactNFA& automaton) const {
 	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
-	out = std::move(this->unreachableStates(automaton));
+	out = std::move(this->reachableStates(automaton));
 }
 
-void UnreachableStates::Visit(void*, const DPDA&) const {
+void ReachableStates::Visit(void*, const DPDA&) const {
 	throw exception::AlibException("Unsupported automaton type DPDA");
 }
 
-void UnreachableStates::Visit(void*, const SinglePopDPDA&) const {
+void ReachableStates::Visit(void*, const SinglePopDPDA&) const {
 	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
 }
 
-void UnreachableStates::Visit(void*, const InputDrivenDPDA&) const {
+void ReachableStates::Visit(void*, const InputDrivenDPDA&) const {
 	throw exception::AlibException("Unsupported automaton type InputDrivenDPDA");
 }
 
-void UnreachableStates::Visit(void*, const InputDrivenNPDA&) const {
+void ReachableStates::Visit(void*, const InputDrivenNPDA&) const {
 	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
 }
 
-void UnreachableStates::Visit(void*, const VisiblyPushdownDPDA&) const {
+void ReachableStates::Visit(void*, const VisiblyPushdownDPDA&) const {
 	throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA");
 }
 
-void UnreachableStates::Visit(void*, const VisiblyPushdownNPDA&) const {
+void ReachableStates::Visit(void*, const VisiblyPushdownNPDA&) const {
 	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
 }
 
-void UnreachableStates::Visit(void*, const RealTimeHeightDeterministicDPDA&) const {
+void ReachableStates::Visit(void*, const RealTimeHeightDeterministicDPDA&) const {
 	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA");
 }
 
-void UnreachableStates::Visit(void*, const RealTimeHeightDeterministicNPDA&) const {
+void ReachableStates::Visit(void*, const RealTimeHeightDeterministicNPDA&) const {
 	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA");
 }
 
-void UnreachableStates::Visit(void*, const NPDA&) const {
+void ReachableStates::Visit(void*, const NPDA&) const {
 	throw exception::AlibException("Unsupported automaton type NPDA");
 }
 
-void UnreachableStates::Visit(void*, const SinglePopNPDA&) const {
+void ReachableStates::Visit(void*, const SinglePopNPDA&) const {
 	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
 }
 
-void UnreachableStates::Visit(void*, const OneTapeDTM&) const {
+void ReachableStates::Visit(void*, const OneTapeDTM&) const {
 	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
 }
 
-const UnreachableStates UnreachableStates::UNREACHABLE_STATES;
+const ReachableStates ReachableStates::REACHABLE_STATES;
 
 } /* namespace properties */
 
diff --git a/alib2algo/src/automaton/properties/UnreachableStates.h b/alib2algo/src/automaton/properties/ReachableStates.h
similarity index 77%
rename from alib2algo/src/automaton/properties/UnreachableStates.h
rename to alib2algo/src/automaton/properties/ReachableStates.h
index bd51109cb87ea4f825fb402e2bc8b7cb711c7f2a..a3f8559c25f8806dcfddbae73fed023fdaf85220 100644
--- a/alib2algo/src/automaton/properties/UnreachableStates.h
+++ b/alib2algo/src/automaton/properties/ReachableStates.h
@@ -1,12 +1,12 @@
 /*
- * UnreachableStates.h
+ * ReachableStates.h
  *
  *  Created on: 23. 3. 2014
  *	  Author: Tomas Pecka
  */
 
-#ifndef UNREACHABLE_STATES_H_
-#define UNREACHABLE_STATES_H_
+#ifndef REACHABLE_STATES_H_
+#define REACHABLE_STATES_H_
 
 #include <algorithm>
 #include <deque>
@@ -19,15 +19,15 @@ namespace automaton {
 
 namespace properties {
 
-class UnreachableStates : public VisitableAutomatonBase::const_visitor_type {
+class ReachableStates : public VisitableAutomatonBase::const_visitor_type {
 public:
-	static std::set<automaton::State> unreachableStates( const automaton::Automaton & automaton );
+	static std::set<automaton::State> reachableStates( const automaton::Automaton & automaton );
 
 	/**
 	 * Removes dead states from FSM. Melichar 2.29
 	 */
 	template<class T>
-	static std::set<automaton::State> unreachableStates( const T & fsm );
+	static std::set<automaton::State> reachableStates( const T & fsm );
 
 private:
 	void Visit(void*, const EpsilonNFA& automaton) const;
@@ -48,11 +48,11 @@ private:
 	void Visit(void*, const SinglePopNPDA& automaton) const;
 	void Visit(void*, const OneTapeDTM& automaton) const;
 
-	static const UnreachableStates UNREACHABLE_STATES;
+	static const ReachableStates REACHABLE_STATES;
 };
 
 } /* namespace properties */
 
 } /* namespace automaton */
 
-#endif /* UNREACHABLE_STATES_H_ */
+#endif /* REACHABLE_STATES_H_ */
diff --git a/alib2algo/src/automaton/properties/UsefullStates.cpp b/alib2algo/src/automaton/properties/UsefullStates.cpp
index 3c5f246937d1930dc1823e3c0448694dd8b8a8d9..c62908e6c58f7683577298c822ab22cf76af160b 100644
--- a/alib2algo/src/automaton/properties/UsefullStates.cpp
+++ b/alib2algo/src/automaton/properties/UsefullStates.cpp
@@ -56,6 +56,7 @@ template std::set<automaton::State> UsefullStates::usefullStates( const automato
 template std::set<automaton::State> UsefullStates::usefullStates( const automaton::NFA & fsm );
 template std::set<automaton::State> UsefullStates::usefullStates( const automaton::CompactNFA & fsm );
 template std::set<automaton::State> UsefullStates::usefullStates( const automaton::ExtendedNFA & fsm );
+template std::set<automaton::State> UsefullStates::usefullStates( const automaton::MultiInitialStateNFA & fsm );
 
 template<>
 std::set<automaton::State> UsefullStates::usefullStates( const automaton::DFA & fsm ) {
diff --git a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp
index 86cdb96c93e298ff508223e26d15df51d022d24f..b6a5312dd40f37ba3e50841bbdb2a6d86efc8c01 100644
--- a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp
+++ b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp
@@ -15,7 +15,7 @@
 #include <automaton/FSM/NFA.h>
 #include <automaton/FSM/DFA.h>
 
-#include "../properties/UnreachableStates.h"
+#include "../properties/ReachableStates.h"
 
 #include "automaton/common/State.h"
 #include "automaton/Automaton.h"
@@ -27,7 +27,7 @@ namespace simplify {
 template<class T>
 T UnreachableStatesRemover::remove( const T & fsm ) {
 	// 1a
-	std::set<automaton::State> Qa = automaton::properties::UnreachableStates::unreachableStates( fsm );
+	std::set<automaton::State> Qa = automaton::properties::ReachableStates::reachableStates( fsm );
 
 	// 2
 	T M(fsm.getInitialState());
@@ -59,7 +59,7 @@ template automaton::ExtendedNFA UnreachableStatesRemover::remove( const automato
 template<>
 automaton::DFA UnreachableStatesRemover::remove( const automaton::DFA & fsm ) {
 	// 1a
-	std::set<automaton::State> Qa = automaton::properties::UnreachableStates::unreachableStates( fsm );
+	std::set<automaton::State> Qa = automaton::properties::ReachableStates::reachableStates( fsm );
 
 	// 2
 	automaton::DFA M(fsm.getInitialState() );
@@ -85,7 +85,7 @@ automaton::DFA UnreachableStatesRemover::remove( const automaton::DFA & fsm ) {
 template<>
 automaton::MultiInitialStateNFA UnreachableStatesRemover::remove( const automaton::MultiInitialStateNFA & fsm ) {
 	// 1a
-	std::set<automaton::State> Qa = automaton::properties::UnreachableStates::unreachableStates( fsm );
+	std::set<automaton::State> Qa = automaton::properties::ReachableStates::reachableStates( fsm );
 
 	// 2
 	automaton::MultiInitialStateNFA M;
diff --git a/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp b/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3070f632768a56bd3c95e4269604cbe6f6e69f6f
--- /dev/null
+++ b/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp
@@ -0,0 +1,185 @@
+/*
+ * ReachableStates.cpp
+ *
+ *  Created on: 23. 3. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#include "ReachableStates.h"
+
+#include <exception/AlibException.h>
+#include <automaton/FSM/ExtendedNFA.h>
+#include <automaton/FSM/CompactNFA.h>
+#include <automaton/FSM/EpsilonNFA.h>
+#include <automaton/FSM/NFA.h>
+#include <automaton/FSM/DFA.h>
+
+#include <set>
+#include <map>
+#include <queue>
+
+namespace automaton {
+
+namespace properties {
+
+namespace efficient {
+
+std::set<automaton::State> ReachableStates::reachableStates(const Automaton& automaton) {
+	std::set<automaton::State> out;
+	automaton.getData().Accept((void*) &out, ReachableStates::REACHABLE_STATES);
+	return out;
+}
+
+template<class T>
+std::set<automaton::State> ReachableStates::reachableStates( const T & fsm ) {
+	std::map<automaton::State, std::set<automaton::State>> transitions;
+	for(const auto& transition : fsm.getTransitions())
+		transitions[transition.first.first].insert(transition.second.begin(), transition.second.end());
+
+	std::deque<automaton::State> queue { fsm.getInitialState( ) };
+	std::set<automaton::State> visited { fsm.getInitialState( ) };
+
+	while( !queue.empty() ) {
+		const std::set<automaton::State>& to = transitions[queue.front()];
+		queue.pop_front();
+
+		for(const automaton::State& process : to)
+			if(visited.insert(process).second) {
+				queue.push_back(std::move(const_cast<automaton::State&>(process)));
+			}
+	}
+
+	return visited;
+}
+
+template std::set<automaton::State> ReachableStates::reachableStates( const automaton::EpsilonNFA & fsm );
+template std::set<automaton::State> ReachableStates::reachableStates( const automaton::NFA & fsm );
+template std::set<automaton::State> ReachableStates::reachableStates( const automaton::CompactNFA & fsm );
+template std::set<automaton::State> ReachableStates::reachableStates( const automaton::ExtendedNFA & fsm );
+
+template<>
+std::set<automaton::State> ReachableStates::reachableStates( const automaton::MultiInitialStateNFA & fsm ) {
+	std::map<automaton::State, std::set<automaton::State>> transitions;
+	for(const auto& transition : fsm.getTransitions())
+		transitions[transition.first.first].insert(transition.second.begin(), transition.second.end());
+
+	std::deque<automaton::State> queue ( fsm.getInitialStates( ).begin(), fsm.getInitialStates().end() );
+	std::set<automaton::State> visited = fsm.getInitialStates( );
+
+	while( !queue.empty() ) {
+		const std::set<automaton::State>& to = transitions[queue.front()];
+		queue.pop_front();
+
+		for(const automaton::State& process : to)
+			if(visited.insert(process).second) {
+				queue.push_back(std::move(const_cast<automaton::State&>(process)));
+			}
+	}
+
+	return visited;
+}
+
+template<>
+std::set<automaton::State> ReachableStates::reachableStates( const automaton::DFA & fsm ) {
+	std::map<automaton::State, std::set<automaton::State>> transitions;
+	for(const auto& transition : fsm.getTransitions())
+		transitions[transition.first.first].insert(transition.second);
+
+	std::deque<automaton::State> queue { fsm.getInitialState( ) };
+	std::set<automaton::State> visited { fsm.getInitialState( ) };
+
+	while( !queue.empty() ) {
+		const std::set<automaton::State>& to = transitions[queue.front()];
+		queue.pop_front();
+
+		for(const automaton::State& process : to)
+			if(visited.insert(process).second) {
+				queue.push_back(std::move(const_cast<automaton::State&>(process)));
+			}
+	}
+
+	return visited;
+}
+
+void ReachableStates::Visit(void* data, const EpsilonNFA& automaton) const {
+	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
+	out = std::move(this->reachableStates(automaton));
+}
+
+void ReachableStates::Visit(void* data, const MultiInitialStateNFA& automaton) const {
+	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
+	out = std::move(this->reachableStates(automaton));
+}
+
+void ReachableStates::Visit(void* data, const NFA& automaton) const {
+	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
+	out = std::move(this->reachableStates(automaton));
+}
+
+void ReachableStates::Visit(void* data, const DFA& automaton) const {
+	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
+	out = std::move(this->reachableStates(automaton));
+}
+
+void ReachableStates::Visit(void* data, const ExtendedNFA& automaton) const {
+	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
+	out = std::move(this->reachableStates(automaton));
+}
+
+void ReachableStates::Visit(void* data, const CompactNFA& automaton) const {
+	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
+	out = std::move(this->reachableStates(automaton));
+}
+
+void ReachableStates::Visit(void*, const DPDA&) const {
+	throw exception::AlibException("Unsupported automaton type DPDA");
+}
+
+void ReachableStates::Visit(void*, const SinglePopDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
+}
+
+void ReachableStates::Visit(void*, const InputDrivenDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type InputDrivenDPDA");
+}
+
+void ReachableStates::Visit(void*, const InputDrivenNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
+}
+
+void ReachableStates::Visit(void*, const VisiblyPushdownDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA");
+}
+
+void ReachableStates::Visit(void*, const VisiblyPushdownNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
+}
+
+void ReachableStates::Visit(void*, const RealTimeHeightDeterministicDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA");
+}
+
+void ReachableStates::Visit(void*, const RealTimeHeightDeterministicNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA");
+}
+
+void ReachableStates::Visit(void*, const NPDA&) const {
+	throw exception::AlibException("Unsupported automaton type NPDA");
+}
+
+void ReachableStates::Visit(void*, const SinglePopNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
+}
+
+void ReachableStates::Visit(void*, const OneTapeDTM&) const {
+	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
+}
+
+const ReachableStates ReachableStates::REACHABLE_STATES;
+
+} /* namespace efficient */
+
+} /* namespace properties */
+
+} /* namespace automaton */
+
diff --git a/alib2elgo/src/automaton/properties/efficient/ReachableStates.h b/alib2elgo/src/automaton/properties/efficient/ReachableStates.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b52d3990d4d7056b8f27804de7f719cb6a25dc9
--- /dev/null
+++ b/alib2elgo/src/automaton/properties/efficient/ReachableStates.h
@@ -0,0 +1,62 @@
+/*
+ * ReachableStates.h
+ *
+ *  Created on: 23. 3. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef EFFICIENT_REACHABLE_STATES_H_
+#define EFFICIENT_REACHABLE_STATES_H_
+
+#include <algorithm>
+#include <deque>
+#include <set>
+
+#include <automaton/common/State.h>
+#include <automaton/Automaton.h>
+
+namespace automaton {
+
+namespace properties {
+
+namespace efficient {
+
+class ReachableStates : public VisitableAutomatonBase::const_visitor_type {
+public:
+	static std::set<automaton::State> reachableStates( const automaton::Automaton & automaton );
+
+	/**
+	 * Removes dead states from FSM. Melichar 2.29
+	 */
+	template<class T>
+	static std::set<automaton::State> reachableStates( const T & fsm );
+
+private:
+	void Visit(void*, const EpsilonNFA& automaton) const;
+	void Visit(void*, const MultiInitialStateNFA& automaton) const;
+	void Visit(void*, const NFA& automaton) const;
+	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 DPDA& automaton) const;
+	void Visit(void*, const SinglePopDPDA& automaton) const;
+	void Visit(void*, const InputDrivenDPDA& automaton) const;
+	void Visit(void*, const InputDrivenNPDA& automaton) const;
+	void Visit(void*, const VisiblyPushdownDPDA& automaton) const;
+	void Visit(void*, const VisiblyPushdownNPDA& automaton) const;
+	void Visit(void*, const RealTimeHeightDeterministicDPDA& automaton) const;
+	void Visit(void*, const RealTimeHeightDeterministicNPDA& automaton) const;
+	void Visit(void*, const NPDA& automaton) const;
+	void Visit(void*, const SinglePopNPDA& automaton) const;
+	void Visit(void*, const OneTapeDTM& automaton) const;
+
+	static const ReachableStates REACHABLE_STATES;
+};
+
+} /* namespace efficient */
+
+} /* namespace properties */
+
+} /* namespace automaton */
+
+#endif /* EFFICIENT_REACHABLE_STATES_H_ */
diff --git a/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp b/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..446ee0da44f08473918b5fe14488edc2af447d34
--- /dev/null
+++ b/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp
@@ -0,0 +1,165 @@
+/*
+ * UsefullStates.cpp
+ *
+ *  Created on: 23. 3. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#include "UsefullStates.h"
+
+#include <exception/AlibException.h>
+#include <automaton/FSM/ExtendedNFA.h>
+#include <automaton/FSM/CompactNFA.h>
+#include <automaton/FSM/EpsilonNFA.h>
+#include <automaton/FSM/NFA.h>
+#include <automaton/FSM/DFA.h>
+
+#include <set>
+#include <map>
+#include <queue>
+
+namespace automaton {
+
+namespace properties {
+
+namespace efficient {
+
+std::set<automaton::State> UsefullStates::usefullStates(const Automaton& automaton) {
+	std::set<automaton::State> out;
+	automaton.getData().Accept((void*) &out, UsefullStates::USEFULL_STATES);
+	return out;
+}
+
+template<class T>
+std::set<automaton::State> UsefullStates::usefullStates( const T & fsm ) {
+	std::map<automaton::State, std::set<automaton::State>> reversedTransitions;
+	for(const auto& transition : fsm.getTransitions())
+		for(const automaton::State& to : transition.second)
+			reversedTransitions[to].insert(transition.first.first);
+
+	std::deque<automaton::State> queue ( fsm.getFinalStates( ).begin(), fsm.getFinalStates().end() );
+	std::set<automaton::State> visited = fsm.getFinalStates( );
+
+	while( !queue.empty() ) {
+		const std::set<automaton::State>& to = reversedTransitions[queue.front()];
+		queue.pop_front();
+
+		for(const automaton::State& process : to)
+			if(visited.insert(process).second) {
+				queue.push_back(std::move(const_cast<automaton::State&>(process)));
+			}
+	}
+
+	return visited;
+}
+
+template std::set<automaton::State> UsefullStates::usefullStates( const automaton::EpsilonNFA & fsm );
+template std::set<automaton::State> UsefullStates::usefullStates( const automaton::NFA & fsm );
+template std::set<automaton::State> UsefullStates::usefullStates( const automaton::CompactNFA & fsm );
+template std::set<automaton::State> UsefullStates::usefullStates( const automaton::ExtendedNFA & fsm );
+template std::set<automaton::State> UsefullStates::usefullStates( const automaton::MultiInitialStateNFA & fsm );
+
+template<>
+std::set<automaton::State> UsefullStates::usefullStates( const automaton::DFA & fsm ) {
+	std::map<automaton::State, std::set<automaton::State>> reversedTransitions;
+	for(const auto& transition : fsm.getTransitions())
+		reversedTransitions[transition.second].insert(transition.first.first);
+
+	std::deque<automaton::State> queue ( fsm.getFinalStates( ).begin(), fsm.getFinalStates().end() );
+	std::set<automaton::State> visited = fsm.getFinalStates( );
+
+	while( !queue.empty() ) {
+		const std::set<automaton::State>& to = reversedTransitions[queue.front()];
+		queue.pop_front();
+
+		for(const automaton::State& process : to)
+			if(visited.insert(process).second) {
+				queue.push_back(std::move(const_cast<automaton::State&>(process)));
+			}
+	}
+
+	return visited;
+}
+
+void UsefullStates::Visit(void* data, const EpsilonNFA& automaton) const {
+	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
+	out = std::move(this->usefullStates(automaton));
+}
+
+void UsefullStates::Visit(void* data, const MultiInitialStateNFA& automaton) const {
+	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
+	out = std::move(this->usefullStates(automaton));
+}
+
+void UsefullStates::Visit(void* data, const NFA& automaton) const {
+	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
+	out = std::move(this->usefullStates(automaton));
+}
+
+void UsefullStates::Visit(void* data, const DFA& automaton) const {
+	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
+	out = std::move(this->usefullStates(automaton));
+}
+
+void UsefullStates::Visit(void* data, const ExtendedNFA& automaton) const {
+	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
+	out = std::move(this->usefullStates(automaton));
+}
+
+void UsefullStates::Visit(void* data, const CompactNFA& automaton) const {
+	std::set<automaton::State> & out = *((std::set<automaton::State>*) data);
+	out = std::move(this->usefullStates(automaton));
+}
+
+void UsefullStates::Visit(void*, const DPDA&) const {
+	throw exception::AlibException("Unsupported automaton type DPDA");
+}
+
+void UsefullStates::Visit(void*, const SinglePopDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
+}
+
+void UsefullStates::Visit(void*, const InputDrivenDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type InputDrivenDPDA");
+}
+
+void UsefullStates::Visit(void*, const InputDrivenNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
+}
+
+void UsefullStates::Visit(void*, const VisiblyPushdownDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA");
+}
+
+void UsefullStates::Visit(void*, const VisiblyPushdownNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
+}
+
+void UsefullStates::Visit(void*, const RealTimeHeightDeterministicDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA");
+}
+
+void UsefullStates::Visit(void*, const RealTimeHeightDeterministicNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA");
+}
+
+void UsefullStates::Visit(void*, const NPDA&) const {
+	throw exception::AlibException("Unsupported automaton type NPDA");
+}
+
+void UsefullStates::Visit(void*, const SinglePopNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
+}
+
+void UsefullStates::Visit(void*, const OneTapeDTM&) const {
+	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
+}
+
+const UsefullStates UsefullStates::USEFULL_STATES;
+
+} /* namespace efficient */
+
+} /* namespace properties */
+
+} /* namespace automaton */
+
diff --git a/alib2elgo/src/automaton/properties/efficient/UsefullStates.h b/alib2elgo/src/automaton/properties/efficient/UsefullStates.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a4117afcaeb63abbbd234485a06992a134ac824
--- /dev/null
+++ b/alib2elgo/src/automaton/properties/efficient/UsefullStates.h
@@ -0,0 +1,62 @@
+/*
+ * UsefullStates.h
+ *
+ *  Created on: 23. 3. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef EFFICIENT_USEFULL_STATES_H_
+#define EFFICIENT_USEFULL_STATES_H_
+
+#include <algorithm>
+#include <deque>
+#include <set>
+
+#include <automaton/common/State.h>
+#include <automaton/Automaton.h>
+
+namespace automaton {
+
+namespace properties {
+
+namespace efficient {
+
+class UsefullStates : public VisitableAutomatonBase::const_visitor_type {
+public:
+	static std::set<automaton::State> usefullStates( const automaton::Automaton & automaton );
+
+	/**
+	 * Removes dead states from FSM. Melichar 2.32
+	 */
+	template<class T>
+	static std::set<automaton::State> usefullStates( const T & fsm );
+
+private:
+	void Visit(void*, const EpsilonNFA& automaton) const;
+	void Visit(void*, const MultiInitialStateNFA& automaton) const;
+	void Visit(void*, const NFA& automaton) const;
+	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 DPDA& automaton) const;
+	void Visit(void*, const SinglePopDPDA& automaton) const;
+	void Visit(void*, const InputDrivenDPDA& automaton) const;
+	void Visit(void*, const InputDrivenNPDA& automaton) const;
+	void Visit(void*, const VisiblyPushdownDPDA& automaton) const;
+	void Visit(void*, const VisiblyPushdownNPDA& automaton) const;
+	void Visit(void*, const RealTimeHeightDeterministicDPDA& automaton) const;
+	void Visit(void*, const RealTimeHeightDeterministicNPDA& automaton) const;
+	void Visit(void*, const NPDA& automaton) const;
+	void Visit(void*, const SinglePopNPDA& automaton) const;
+	void Visit(void*, const OneTapeDTM& automaton) const;
+
+	static const UsefullStates USEFULL_STATES;
+};
+
+} /* namespace efficient */
+
+} /* namespace properties */
+
+} /* namespace automaton */
+
+#endif /* EFFICIENT_USEFULL_STATES_H_ */
diff --git a/alib2elgo/src/automaton/simplify/efficient/Trim.cpp b/alib2elgo/src/automaton/simplify/efficient/Trim.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..627c532b2f93f285085a0369f1509e566a51739a
--- /dev/null
+++ b/alib2elgo/src/automaton/simplify/efficient/Trim.cpp
@@ -0,0 +1,129 @@
+/*
+ * Trim.cpp
+ *
+ *  Created on: 23. 3. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#include "Trim.h"
+#include "UselessStatesRemover.h"
+#include "UnreachableStatesRemover.h"
+
+#include <exception/AlibException.h>
+#include <automaton/FSM/ExtendedNFA.h>
+#include <automaton/FSM/CompactNFA.h>
+#include <automaton/FSM/EpsilonNFA.h>
+#include <automaton/FSM/NFA.h>
+#include <automaton/FSM/DFA.h>
+
+#include "automaton/common/State.h"
+#include "automaton/Automaton.h"
+
+namespace automaton {
+
+namespace simplify {
+
+namespace efficient {
+
+template<class T>
+T Trim::trim( const T & fsm ) {
+	return UnreachableStatesRemover::remove(UselessStatesRemover::remove(fsm));
+}
+
+template automaton::EpsilonNFA Trim::trim( const automaton::EpsilonNFA & fsm );
+template automaton::NFA Trim::trim( const automaton::NFA & fsm );
+template automaton::MultiInitialStateNFA Trim::trim( const automaton::MultiInitialStateNFA & fsm );
+template automaton::CompactNFA Trim::trim( const automaton::CompactNFA & fsm );
+template automaton::ExtendedNFA Trim::trim( const automaton::ExtendedNFA & fsm );
+template automaton::DFA Trim::trim( const automaton::DFA & fsm );
+
+automaton::Automaton Trim::trim(const automaton::Automaton& automaton) {
+	automaton::Automaton* out = NULL;
+	automaton.getData().Accept((void*) &out, Trim::TRIM);
+	automaton::Automaton res = std::move(*out);
+	delete out;
+	return res;
+}
+
+void Trim::Visit(void* data, const automaton::EpsilonNFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->trim(automaton));
+}
+
+void Trim::Visit(void* data, const automaton::MultiInitialStateNFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->trim(automaton));
+}
+
+void Trim::Visit(void* data, const automaton::NFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->trim(automaton));
+}
+
+void Trim::Visit(void* data, const automaton::DFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->trim(automaton));
+}
+
+void Trim::Visit(void* data, const automaton::ExtendedNFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->trim(automaton));
+}
+
+void Trim::Visit(void* data, const automaton::CompactNFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->trim(automaton));
+}
+
+void Trim::Visit(void*, const automaton::DPDA&) const {
+	throw exception::AlibException("Unsupported automaton type DPDA");
+}
+
+void Trim::Visit(void*, const automaton::SinglePopDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
+}
+
+void Trim::Visit(void*, const automaton::InputDrivenDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type InputDrivenDPDA");
+}
+
+void Trim::Visit(void*, const automaton::InputDrivenNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
+}
+
+void Trim::Visit(void*, const automaton::VisiblyPushdownDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA");
+}
+
+void Trim::Visit(void*, const automaton::VisiblyPushdownNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
+}
+
+void Trim::Visit(void*, const automaton::RealTimeHeightDeterministicDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA");
+}
+
+void Trim::Visit(void*, const automaton::RealTimeHeightDeterministicNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA");
+}
+
+void Trim::Visit(void*, const automaton::NPDA&) const {
+	throw exception::AlibException("Unsupported automaton type NPDA");
+}
+
+void Trim::Visit(void*, const automaton::SinglePopNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
+}
+
+void Trim::Visit(void*, const automaton::OneTapeDTM&) const {
+	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
+}
+
+const Trim Trim::TRIM;
+
+} /* namespace efficient */
+
+} /* namespace simplify */
+
+} /* namespace automaton */
+
diff --git a/alib2elgo/src/automaton/simplify/efficient/Trim.h b/alib2elgo/src/automaton/simplify/efficient/Trim.h
new file mode 100644
index 0000000000000000000000000000000000000000..8048d0cd9b6d94e2ad7e8d29db5c5f54a999430f
--- /dev/null
+++ b/alib2elgo/src/automaton/simplify/efficient/Trim.h
@@ -0,0 +1,60 @@
+/*
+ * Trim.h
+ *
+ *  Created on: 23. 3. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef EFFICIENT_AUTOMATON_TRIM_H_
+#define EFFICIENT_AUTOMAONT_TRIM_H_
+
+#include <algorithm>
+#include <deque>
+#include <set>
+#include <automaton/Automaton.h>
+
+namespace automaton {
+
+namespace simplify {
+
+namespace efficient {
+
+class Trim : public automaton::VisitableAutomatonBase::const_visitor_type {
+public:
+	static automaton::Automaton trim( const automaton::Automaton & automaton );
+
+	/**
+	 * Removes dead states from FSM. Melichar 2.29
+	 */
+	template<class T>
+	static T trim( const T & fsm );
+
+private:
+	void Visit(void*, const automaton::EpsilonNFA& automaton) const;
+	void Visit(void*, const automaton::MultiInitialStateNFA& automaton) const;
+	void Visit(void*, const automaton::NFA& automaton) const;
+	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::DPDA& automaton) const;
+	void Visit(void*, const automaton::SinglePopDPDA& automaton) const;
+	void Visit(void*, const automaton::InputDrivenDPDA& automaton) const;
+	void Visit(void*, const automaton::InputDrivenNPDA& automaton) const;
+	void Visit(void*, const automaton::VisiblyPushdownDPDA& automaton) const;
+	void Visit(void*, const automaton::VisiblyPushdownNPDA& automaton) const;
+	void Visit(void*, const automaton::RealTimeHeightDeterministicDPDA& automaton) const;
+	void Visit(void*, const automaton::RealTimeHeightDeterministicNPDA& automaton) const;
+	void Visit(void*, const automaton::NPDA& automaton) const;
+	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
+	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+
+	static const Trim TRIM;
+};
+
+} /* namespace efficient */
+
+} /* namespace simplify */
+
+} /* namespace automaton */
+
+#endif /* EFFICIENT_AUTOMATON_TRIM_H_ */
diff --git a/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.cpp b/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f0b7c582ea1f31690796251ee3cdd937eb831e1b
--- /dev/null
+++ b/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.cpp
@@ -0,0 +1,204 @@
+/*
+ * UnreachableStatesRemover.cpp
+ *
+ *  Created on: 23. 3. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#include "UnreachableStatesRemover.h"
+
+#include <exception/AlibException.h>
+#include <automaton/FSM/ExtendedNFA.h>
+#include <automaton/FSM/CompactNFA.h>
+#include <automaton/FSM/EpsilonNFA.h>
+#include <automaton/FSM/MultiInitialStateNFA.h>
+#include <automaton/FSM/NFA.h>
+#include <automaton/FSM/DFA.h>
+
+#include "../../properties/efficient/ReachableStates.h"
+
+#include "automaton/common/State.h"
+#include "automaton/Automaton.h"
+
+namespace automaton {
+
+namespace simplify {
+
+namespace efficient {
+
+template<class T>
+T UnreachableStatesRemover::remove( const T & fsm ) {
+	// 1a
+	std::set<automaton::State> Qa = automaton::properties::efficient::ReachableStates::reachableStates( fsm );
+
+	// 2
+	T M(fsm.getInitialState());
+
+	for( const auto & q : Qa )
+		M.addState( q );
+
+	for( const auto & a : fsm.getInputAlphabet( ) )
+		M.addInputSymbol( a );
+
+	for( const auto & transition : fsm.getTransitions( ) )
+		if( Qa.count( transition.first.first ) )
+			for(const auto& to : transition.second )
+				M.addTransition( transition.first.first, transition.first.second, to );
+
+	std::set<automaton::State> intersect;
+	std::set_intersection( fsm.getFinalStates( ).begin(), fsm.getFinalStates( ).end(), Qa.begin( ), Qa.end( ), std::inserter( intersect, intersect.begin( ) ) );
+	for( auto const & state : intersect )
+		M.addFinalState( state );
+
+	return M;
+}
+
+template automaton::EpsilonNFA UnreachableStatesRemover::remove( const automaton::EpsilonNFA & fsm );
+template automaton::NFA UnreachableStatesRemover::remove( const automaton::NFA & fsm );
+template automaton::CompactNFA UnreachableStatesRemover::remove( const automaton::CompactNFA & fsm );
+template automaton::ExtendedNFA UnreachableStatesRemover::remove( const automaton::ExtendedNFA & fsm );
+
+template<>
+automaton::DFA UnreachableStatesRemover::remove( const automaton::DFA & fsm ) {
+	// 1a
+	std::set<automaton::State> Qa = automaton::properties::efficient::ReachableStates::reachableStates( fsm );
+
+	// 2
+	automaton::DFA M(fsm.getInitialState() );
+
+	for( const auto & q : Qa )
+		M.addState( q );
+
+	for( const auto & a : fsm.getInputAlphabet( ) )
+		M.addInputSymbol( a );
+
+	for( const auto & transition : fsm.getTransitions( ) )
+		if( Qa.count( transition.first.first ) )
+			M.addTransition( transition.first.first, transition.first.second, transition.second );
+
+	std::set<automaton::State> intersect;
+	std::set_intersection( fsm.getFinalStates( ).begin(), fsm.getFinalStates( ).end(), Qa.begin( ), Qa.end( ), std::inserter( intersect, intersect.begin( ) ) );
+	for( auto const & state : intersect )
+		M.addFinalState( state );
+
+	return M;
+}
+
+template<>
+automaton::MultiInitialStateNFA UnreachableStatesRemover::remove( const automaton::MultiInitialStateNFA & fsm ) {
+	// 1a
+	std::set<automaton::State> Qa = automaton::properties::efficient::ReachableStates::reachableStates( fsm );
+
+	// 2
+	automaton::MultiInitialStateNFA M;
+
+	for( const auto & q : Qa )
+		M.addState( q );
+
+	M.setInitialStates( fsm.getInitialStates() );
+
+	for( const auto & a : fsm.getInputAlphabet( ) )
+		M.addInputSymbol( a );
+
+	for( const auto & transition : fsm.getTransitions( ) )
+		if( Qa.count( transition.first.first ) )
+			for(const auto& to : transition.second )
+				M.addTransition( transition.first.first, transition.first.second, to );
+
+	std::set<automaton::State> intersect;
+	std::set_intersection( fsm.getFinalStates( ).begin(), fsm.getFinalStates( ).end(), Qa.begin( ), Qa.end( ), std::inserter( intersect, intersect.begin( ) ) );
+	for( auto const & state : intersect )
+		M.addFinalState( state );
+
+	return M;
+}
+
+automaton::Automaton UnreachableStatesRemover::remove(const automaton::Automaton& automaton) {
+	automaton::Automaton* out = NULL;
+	automaton.getData().Accept((void*) &out, UnreachableStatesRemover::UNREACHABLE_STATES_REMOVER);
+	automaton::Automaton res = std::move(*out);
+	delete out;
+	return res;
+}
+
+void UnreachableStatesRemover::Visit(void* data, const automaton::EpsilonNFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void UnreachableStatesRemover::Visit(void* data, const automaton::MultiInitialStateNFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void UnreachableStatesRemover::Visit(void* data, const automaton::NFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void UnreachableStatesRemover::Visit(void* data, const automaton::DFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void UnreachableStatesRemover::Visit(void* data, const automaton::ExtendedNFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void UnreachableStatesRemover::Visit(void* data, const automaton::CompactNFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void UnreachableStatesRemover::Visit(void*, const automaton::DPDA&) const {
+	throw exception::AlibException("Unsupported automaton type DPDA");
+}
+
+void UnreachableStatesRemover::Visit(void*, const automaton::SinglePopDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
+}
+
+void UnreachableStatesRemover::Visit(void*, const automaton::InputDrivenDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type InputDrivenDPDA");
+}
+
+void UnreachableStatesRemover::Visit(void*, const automaton::InputDrivenNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
+}
+
+void UnreachableStatesRemover::Visit(void*, const automaton::VisiblyPushdownDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA");
+}
+
+void UnreachableStatesRemover::Visit(void*, const automaton::VisiblyPushdownNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
+}
+
+void UnreachableStatesRemover::Visit(void*, const automaton::RealTimeHeightDeterministicDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA");
+}
+
+void UnreachableStatesRemover::Visit(void*, const automaton::RealTimeHeightDeterministicNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA");
+}
+
+void UnreachableStatesRemover::Visit(void*, const automaton::NPDA&) const {
+	throw exception::AlibException("Unsupported automaton type NPDA");
+}
+
+void UnreachableStatesRemover::Visit(void*, const automaton::SinglePopNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
+}
+
+void UnreachableStatesRemover::Visit(void*, const automaton::OneTapeDTM&) const {
+	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
+}
+
+const UnreachableStatesRemover UnreachableStatesRemover::UNREACHABLE_STATES_REMOVER;
+
+} /* namespace efficient */
+
+} /* namespace simplify */
+
+} /* namespace automaton */
diff --git a/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h b/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h
new file mode 100644
index 0000000000000000000000000000000000000000..4fa148ed79672df6a2f38ef01ed4585adb2fe3db
--- /dev/null
+++ b/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h
@@ -0,0 +1,60 @@
+/*
+ * UnreachableStatesRemover.h
+ *
+ *  Created on: 23. 3. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef EFFICIENT_UNREACHABLE_STATES_REMOVER_H_
+#define EFFICIENT_UNREACHABLE_STATES_REMOVER_H_
+
+#include <algorithm>
+#include <deque>
+#include <set>
+#include <automaton/Automaton.h>
+
+namespace automaton {
+
+namespace simplify {
+
+namespace efficient {
+
+class UnreachableStatesRemover : public automaton::VisitableAutomatonBase::const_visitor_type {
+public:
+	static automaton::Automaton remove( const automaton::Automaton & automaton );
+
+	/**
+	 * Removes dead states from FSM. Melichar 2.29
+	 */
+	template<class T>
+	static T remove( const T & automaton );
+
+private:
+	void Visit(void*, const automaton::EpsilonNFA& automaton) const;
+	void Visit(void*, const automaton::MultiInitialStateNFA& automaton) const;
+	void Visit(void*, const automaton::NFA& automaton) const;
+	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::DPDA& automaton) const;
+	void Visit(void*, const automaton::SinglePopDPDA& automaton) const;
+	void Visit(void*, const automaton::InputDrivenDPDA& automaton) const;
+	void Visit(void*, const automaton::InputDrivenNPDA& automaton) const;
+	void Visit(void*, const automaton::VisiblyPushdownDPDA& automaton) const;
+	void Visit(void*, const automaton::VisiblyPushdownNPDA& automaton) const;
+	void Visit(void*, const automaton::RealTimeHeightDeterministicDPDA& automaton) const;
+	void Visit(void*, const automaton::RealTimeHeightDeterministicNPDA& automaton) const;
+	void Visit(void*, const automaton::NPDA& automaton) const;
+	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
+	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+
+	static const UnreachableStatesRemover UNREACHABLE_STATES_REMOVER;
+};
+
+} /* namespace efficient */
+
+} /* namespace simplify */
+
+} /* namespace automaton */
+
+#endif /* EFFICIENT_UNREACHABLE_STATES_REMOVER_H_ */
diff --git a/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.cpp b/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..536ed54becb0a4358eb5144e91beac3f96eb80cf
--- /dev/null
+++ b/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.cpp
@@ -0,0 +1,213 @@
+/*
+ * UselessStatesRemover.cpp
+ *
+ *  Created on: 23. 3. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#include "UselessStatesRemover.h"
+
+#include <exception/AlibException.h>
+#include <automaton/FSM/ExtendedNFA.h>
+#include <automaton/FSM/CompactNFA.h>
+#include <automaton/FSM/EpsilonNFA.h>
+#include <automaton/FSM/MultiInitialStateNFA.h>
+#include <automaton/FSM/NFA.h>
+#include <automaton/FSM/DFA.h>
+
+#include "../../properties/efficient/UsefullStates.h"
+
+#include "automaton/common/State.h"
+#include "automaton/Automaton.h"
+
+namespace automaton {
+
+namespace simplify {
+
+namespace efficient {
+
+template<class T>
+T UselessStatesRemover::remove( const T & fsm ) {
+	// 1.
+	std::set<automaton::State> Qu = automaton::properties::efficient::UsefullStates::usefullStates( fsm );
+
+	// 2.
+	T M(fsm.getInitialState());
+
+	for( const auto & a : fsm.getInputAlphabet( ) )
+		M.addInputSymbol( a );
+
+	if(Qu.size() == 0) {
+		return M;
+	}
+
+	for( const auto & q : Qu )
+		M.addState( q );
+
+	for( const auto & t : fsm.getTransitions( ) )
+		for( const auto & to : t.second )
+			if( /* this part is not needed Qu.count(t.first.first) ) && */ Qu.count(to) )
+				M.addTransition( t.first.first, t.first.second, to );
+
+	for( const auto & q : fsm.getFinalStates( ) )
+		M.addFinalState( q );
+
+	return M;
+}
+
+template automaton::EpsilonNFA UselessStatesRemover::remove( const automaton::EpsilonNFA & fsm );
+template automaton::NFA UselessStatesRemover::remove( const automaton::NFA & fsm );
+template automaton::CompactNFA UselessStatesRemover::remove( const automaton::CompactNFA & fsm );
+template automaton::ExtendedNFA UselessStatesRemover::remove( const automaton::ExtendedNFA & fsm );
+
+template<>
+automaton::DFA UselessStatesRemover::remove( const automaton::DFA & fsm ) {
+	// 1.
+	std::set<automaton::State> Qu = automaton::properties::efficient::UsefullStates::usefullStates( fsm );
+
+	// 2.
+	automaton::DFA M ( fsm.getInitialState () );
+
+	for( const auto & a : fsm.getInputAlphabet( ) )
+		M.addInputSymbol( a );
+
+	if(Qu.size() == 0) {
+		return M;
+	}
+
+	for( const auto & q : Qu )
+		M.addState( q );
+
+	for( const auto & t : fsm.getTransitions( ) )
+		if( /* this part is not needed Qu.count( t.first.first ) && */ Qu.count( t.second ) )
+			M.addTransition( t.first.first, t.first.second, t.second );
+
+	for( const auto & q : fsm.getFinalStates( ) )
+		M.addFinalState( q );
+
+	return M;
+}
+
+template<>
+automaton::MultiInitialStateNFA UselessStatesRemover::remove( const automaton::MultiInitialStateNFA & fsm ) {
+	// 1.
+	std::set<automaton::State> Qu = automaton::properties::efficient::UsefullStates::usefullStates( fsm );
+
+	// 2.
+	automaton::MultiInitialStateNFA M;
+
+	for( const auto & a : fsm.getInputAlphabet( ) )
+		M.addInputSymbol( a );
+
+	if(Qu.size() == 0) {
+		return M;
+	}
+
+	for( const auto & q : Qu )
+		M.addState( q );
+
+	for(const auto& init : fsm.getInitialStates()) {
+		if( Qu.count(init) )
+			M.addInitialState( init );
+	}
+
+	for( const auto & t : fsm.getTransitions( ) )
+		for( const auto & to : t.second )
+			if( Qu.count(to) )
+				M.addTransition( t.first.first, t.first.second, to );
+
+	for( const auto & q : fsm.getFinalStates( ) )
+		M.addFinalState( q );
+
+	return M;
+}
+
+automaton::Automaton UselessStatesRemover::remove(const automaton::Automaton& automaton) {
+	automaton::Automaton* out = NULL;
+	automaton.getData().Accept((void*) &out, UselessStatesRemover::USELESS_STATES_REMOVER);
+	automaton::Automaton res = std::move(*out);
+	delete out;
+	return res;
+}
+
+void UselessStatesRemover::Visit(void* data, const automaton::EpsilonNFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void UselessStatesRemover::Visit(void* data, const automaton::MultiInitialStateNFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void UselessStatesRemover::Visit(void* data, const automaton::NFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void UselessStatesRemover::Visit(void* data, const automaton::DFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void UselessStatesRemover::Visit(void* data, const automaton::ExtendedNFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void UselessStatesRemover::Visit(void* data, const automaton::CompactNFA& automaton) const {
+	automaton::Automaton* & out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->remove(automaton));
+}
+
+void UselessStatesRemover::Visit(void*, const automaton::DPDA&) const {
+	throw exception::AlibException("Unsupported automaton type DPDA");
+}
+
+void UselessStatesRemover::Visit(void*, const automaton::SinglePopDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
+}
+
+void UselessStatesRemover::Visit(void*, const automaton::InputDrivenDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type InputDrivenDPDA");
+}
+
+void UselessStatesRemover::Visit(void*, const automaton::InputDrivenNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
+}
+
+void UselessStatesRemover::Visit(void*, const automaton::VisiblyPushdownDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA");
+}
+
+void UselessStatesRemover::Visit(void*, const automaton::VisiblyPushdownNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
+}
+
+void UselessStatesRemover::Visit(void*, const automaton::RealTimeHeightDeterministicDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA");
+}
+
+void UselessStatesRemover::Visit(void*, const automaton::RealTimeHeightDeterministicNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA");
+}
+
+void UselessStatesRemover::Visit(void*, const automaton::NPDA&) const {
+	throw exception::AlibException("Unsupported automaton type NPDA");
+}
+
+void UselessStatesRemover::Visit(void*, const automaton::SinglePopNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
+}
+
+void UselessStatesRemover::Visit(void*, const automaton::OneTapeDTM&) const {
+	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
+}
+
+const UselessStatesRemover UselessStatesRemover::USELESS_STATES_REMOVER;
+
+} /* namespace efficient */
+
+} /* namespace simplify */
+
+} /* namespace automaton */
diff --git a/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h b/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h
new file mode 100644
index 0000000000000000000000000000000000000000..df0b85d6f03bf7c13d33bffd630d1a8bc032b363
--- /dev/null
+++ b/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h
@@ -0,0 +1,60 @@
+/*
+ * UselessStatesRemover.h
+ *
+ *  Created on: 23. 3. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef EFFICIENT_USELESS_STATES_REMOVER_H_
+#define EFFICIENT_USELESS_STATES_REMOVER_H_
+
+#include <algorithm>
+#include <deque>
+#include <set>
+#include <automaton/Automaton.h>
+
+namespace automaton {
+
+namespace simplify {
+
+namespace efficient {
+
+class UselessStatesRemover : public automaton::VisitableAutomatonBase::const_visitor_type {
+public:
+	static automaton::Automaton remove( const automaton::Automaton & automaton );
+
+	/**
+	 * Removes dead states from FSM. Melichar 2.29
+	 */
+	template<class T>
+	static T remove( const T & automaton );
+
+private:
+	void Visit(void*, const automaton::EpsilonNFA& automaton) const;
+	void Visit(void*, const automaton::MultiInitialStateNFA& automaton) const;
+	void Visit(void*, const automaton::NFA& automaton) const;
+	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::DPDA& automaton) const;
+	void Visit(void*, const automaton::SinglePopDPDA& automaton) const;
+	void Visit(void*, const automaton::InputDrivenDPDA& automaton) const;
+	void Visit(void*, const automaton::InputDrivenNPDA& automaton) const;
+	void Visit(void*, const automaton::VisiblyPushdownDPDA& automaton) const;
+	void Visit(void*, const automaton::VisiblyPushdownNPDA& automaton) const;
+	void Visit(void*, const automaton::RealTimeHeightDeterministicDPDA& automaton) const;
+	void Visit(void*, const automaton::RealTimeHeightDeterministicNPDA& automaton) const;
+	void Visit(void*, const automaton::NPDA& automaton) const;
+	void Visit(void*, const automaton::SinglePopNPDA& automaton) const;
+	void Visit(void*, const automaton::OneTapeDTM& automaton) const;
+
+	static const UselessStatesRemover USELESS_STATES_REMOVER;
+};
+
+} /* namespace efficient */
+
+} /* namespace simplify */
+
+} /* namespace automaton */
+
+#endif /* EFFICIENT_USELESS_STATES_REMOVER_H_ */
diff --git a/alib2elgo/test-src/automaton/simplify/efficient/trimTest.cpp b/alib2elgo/test-src/automaton/simplify/efficient/trimTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cbc1fae5418f5760ac23e410728c0ab6889968ff
--- /dev/null
+++ b/alib2elgo/test-src/automaton/simplify/efficient/trimTest.cpp
@@ -0,0 +1,37 @@
+#include <list>
+#include "trimTest.h"
+
+#include "automaton/simplify/Trim.h"
+
+#include "automaton/FSM/DFA.h"
+
+#define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y))
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( trimTest, "automaton" );
+CPPUNIT_TEST_SUITE_REGISTRATION( trimTest );
+
+void trimTest::setUp() {
+}
+
+void trimTest::tearDown() {
+}
+
+void trimTest::testTrimAutomaton() {
+  automaton::DFA automaton(automaton::State(1));
+
+  automaton.addState(automaton::State(1));
+  automaton.addState(automaton::State(2));
+  automaton.addState(automaton::State(3));
+  automaton.addInputSymbol(alphabet::symbolFrom("a"));
+  automaton.addInputSymbol(alphabet::symbolFrom("b"));
+  
+  automaton.addTransition(automaton::State(1), alphabet::symbolFrom("a"), automaton::State(2));
+  automaton.addTransition(automaton::State(2), alphabet::symbolFrom("b"), automaton::State(1));
+  automaton.addTransition(automaton::State(3), alphabet::symbolFrom("b"), automaton::State(1));
+
+  automaton.addFinalState(automaton::State(1));
+  
+  automaton::DFA trimed = automaton::simplify::Trim::trim(automaton);
+
+  CPPUNIT_ASSERT(trimed.getStates().size() == 2);
+}
diff --git a/alib2elgo/test-src/automaton/simplify/efficient/trimTest.h b/alib2elgo/test-src/automaton/simplify/efficient/trimTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b6782294c816b11bea2f297e8708c6654536cc1
--- /dev/null
+++ b/alib2elgo/test-src/automaton/simplify/efficient/trimTest.h
@@ -0,0 +1,19 @@
+#ifndef TRIM_TEST_H_
+#define TRIM_TEST_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class trimTest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( trimTest );
+  CPPUNIT_TEST( testTrimAutomaton );
+  CPPUNIT_TEST_SUITE_END();
+
+public:
+  void setUp();
+  void tearDown();
+
+  void testTrimAutomaton();
+};
+
+#endif  // TRIM_TEST_H_
diff --git a/atrim2/src/atrim.cpp b/atrim2/src/atrim.cpp
index 86cb4dd4f3ac5a0de6f4c03006f097f9dbdbf83e..927ca8a8f01fc608e99f3fadf1de7d4f3fa9eaba 100644
--- a/atrim2/src/atrim.cpp
+++ b/atrim2/src/atrim.cpp
@@ -14,8 +14,11 @@
 #include "grammar/simplify/UnproductiveSymbolsRemover.h"
 #include "grammar/simplify/UnreachableSymbolsRemover.h"
 #include "automaton/simplify/Trim.h"
+#include "automaton/simplify/efficient/Trim.h"
 #include "automaton/simplify/UselessStatesRemover.h"
+#include "automaton/simplify/efficient/UselessStatesRemover.h"
 #include "automaton/simplify/UnreachableStatesRemover.h"
+#include "automaton/simplify/efficient/UnreachableStatesRemover.h"
 #include "regexp/simplify/RegExpOptimize.h"
 
 grammar::Grammar trimGrammar(const grammar::Grammar& g, bool del_unreachable, bool del_unproductive) {
@@ -38,6 +41,16 @@ automaton::Automaton trimAutomaton(const automaton::Automaton& g, bool del_unrea
 	return automaton::simplify::Trim::trim( g );
 }
 
+automaton::Automaton efficientTrimAutomaton(const automaton::Automaton& g, bool del_unreachable, bool del_useless) {
+	if( del_unreachable && del_useless )
+		return automaton::simplify::efficient::Trim::trim( g );
+	if( del_unreachable )
+		return automaton::simplify::efficient::UnreachableStatesRemover::remove( g );
+	if( del_useless )
+		return automaton::simplify::efficient::UselessStatesRemover::remove( g );
+	return automaton::simplify::efficient::Trim::trim( g );
+}
+
 regexp::RegExp optimizeRegExp(const regexp::RegExp& r) {
 	return regexp::simplify::RegExpOptimize::optimize( r );
 }
@@ -58,6 +71,9 @@ int main(int argc, char* argv[]) {
 		TCLAP::ValueArg<std::string> input(	"i",	"input",	"Input to trim",							false,	"-",	"file");
 		cmd.add( input );
 
+		TCLAP::SwitchArg efficient(		"e",	"efficient",	"Use efficient implementation",		false);
+		cmd.add( efficient );
+
 		cmd.parse(argc, argv);
 
 		std::list<sax::Token> tokens;
@@ -74,9 +90,10 @@ int main(int argc, char* argv[]) {
 		if( alib::XmlDataFactory::first<automaton::Automaton>(tokens)) {
 			automaton::Automaton automaton = alib::XmlDataFactory::fromTokens<automaton::Automaton>(tokens);
 
-			automaton::Automaton res = trimAutomaton(automaton, unreachable.getValue(), useless.getValue() );
-
-			alib::XmlDataFactory::toStdout( res );
+			if(efficient.getValue())
+				alib::XmlDataFactory::toStdout( efficientTrimAutomaton(automaton, unreachable.getValue(), useless.getValue() ) );
+			else
+				alib::XmlDataFactory::toStdout( trimAutomaton(automaton, unreachable.getValue(), useless.getValue() ) );
 			return 0;
 		} else if( alib::XmlDataFactory::first<grammar::Grammar>(tokens)) {
 			grammar::Grammar grammar = alib::XmlDataFactory::fromTokens<grammar::Grammar>(tokens);
diff --git a/tests.aconversion.sh b/tests.aconversion.sh
index ab59217e272e181b3415e9a6d1cd7f830bf74a7d..81d042a845951e074564eb34d31891ea0f615a67 100755
--- a/tests.aconversion.sh
+++ b/tests.aconversion.sh
@@ -56,7 +56,7 @@ function generateNFA {
 # $1 = command for conversion. Output of such command must be (eps-)NFA !!
 # $2 = automaton
 function runTest2 {
-	MDFA="./aepsilon2 -e | ./adeterminize2 | ./atrim2 | ./aminimize2 | ./anormalize2 --labels automaton"
+	MDFA="./aepsilon2 -e | ./adeterminize2 | ./atrim2 -e | ./aminimize2 | ./anormalize2 --labels automaton"
 
 	OUT=`timeout $TESTCASE_TIMEOUT bash -c "./acompare2 <(cat $2 | $1 | $MDFA ) <(cat $2 | $MDFA)"`
 	RET=$?