From 67c133850039bc686767ec305711618894e16440 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Fri, 29 Mar 2019 15:02:02 +0100
Subject: [PATCH] use multimap in EpsilonNFA

---
 .../src/automaton/convert/ToRegExpAlgebraic.h |   6 +-
 .../automaton/generate/RandomizeAutomaton.h   |   5 +-
 .../automaton/properties/AllEpsilonClosure.h  |   5 +-
 .../src/automaton/properties/EpsilonClosure.h |  11 +-
 .../automaton/properties/ReachableStates.h    |  40 ++++
 alib2algo/src/automaton/run/Run.h             |   7 +-
 .../simplify/EpsilonRemoverIncoming.h         |  10 +-
 .../simplify/EpsilonRemoverOutgoing.h         |   2 +-
 .../simplify/UnreachableStatesRemover.h       |  34 +++
 .../automaton/simplify/UselessStatesRemover.h |  36 +++
 .../AutomataConcatenationEpsilonTransition.h  |   6 +-
 .../AutomataUnionEpsilonTransition.h          |   6 +-
 alib2aux/src/convert/DotConverter.h           |  24 +-
 alib2aux/src/convert/GasTexConverter.h        |  26 +--
 alib2aux/src/convert/TikZConverter.h          |  28 ++-
 alib2data/src/automaton/FSM/CompactNFA.h      |   4 +-
 alib2data/src/automaton/FSM/EpsilonNFA.h      | 221 ++++++++----------
 alib2data/src/automaton/FSM/ExtendedNFA.h     |   4 +-
 .../FSM/MultiInitialStateEpsilonNFA.h         |   2 +-
 alib2data/src/automaton/FSM/NFA.h             |  26 +--
 alib2data/src/automaton/xml/FSM/EpsilonNFA.h  |  15 +-
 .../test-src/automaton/AutomatonTest.cpp      |   6 +
 .../properties/efficient/AllEpsilonClosure.h  |  27 ++-
 .../properties/efficient/ReachableStates.h    |  24 ++
 .../properties/efficient/UsefulStates.h       |  24 ++
 .../efficient/EpsilonRemoverIncoming.h        |  10 +-
 .../efficient/EpsilonRemoverOutgoing.h        |   9 +-
 .../efficient/UnreachableStatesRemover.h      |  28 +++
 .../simplify/efficient/UselessStatesRemover.h |  30 +++
 .../src/automaton/string/FSM/EpsilonNFA.h     |  20 +-
 30 files changed, 436 insertions(+), 260 deletions(-)

diff --git a/alib2algo/src/automaton/convert/ToRegExpAlgebraic.h b/alib2algo/src/automaton/convert/ToRegExpAlgebraic.h
index a10f3f6917..8144e092f4 100644
--- a/alib2algo/src/automaton/convert/ToRegExpAlgebraic.h
+++ b/alib2algo/src/automaton/convert/ToRegExpAlgebraic.h
@@ -86,12 +86,10 @@ regexp::UnboundedRegExp < SymbolType > ToRegExpAlgebraic::convert ( const automa
 		solver.addEquation ( q, regexp::UnboundedRegExpEpsilon < SymbolType > { } );
 
 	for ( const auto & p : automaton.getSymbolTransitions ( ) )
-		for ( const StateType & q : p.second )
-			solver.addEquation ( p.first.first, q, regexp::UnboundedRegExpSymbol < SymbolType > { p.first.second } );
+		solver.addEquation ( p.first.first, p.second, regexp::UnboundedRegExpSymbol < SymbolType > { p.first.second } );
 
 	for( const auto & p : automaton.getEpsilonTransitions ( ) )
-		for ( const StateType & q : p.second )
-			solver.addEquation ( p.first, q, regexp::UnboundedRegExpEpsilon < SymbolType > { } );
+		solver.addEquation ( p.first, p.second, regexp::UnboundedRegExpEpsilon < SymbolType > { } );
 
 	return solver.solve ( automaton.getInitialState ( ) );
 }
diff --git a/alib2algo/src/automaton/generate/RandomizeAutomaton.h b/alib2algo/src/automaton/generate/RandomizeAutomaton.h
index 51815ffc2b..d57f6a5014 100644
--- a/alib2algo/src/automaton/generate/RandomizeAutomaton.h
+++ b/alib2algo/src/automaton/generate/RandomizeAutomaton.h
@@ -141,9 +141,8 @@ automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > RandomizeAutomaton:
 	for ( const StateType & finalState : origFSM.getFinalStates ( ) )
 		res.addFinalState ( statePermutationMap.find ( finalState )->second );
 
-	for ( const std::pair < std::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : origFSM.getTransitions ( ) )
-		for ( const StateType & target : transition.second )
-			res.addTransition ( statePermutationMap.find ( transition.first.first )->second, transition.first.second, statePermutationMap.find ( target )->second );
+	for ( const std::pair < std::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & transition : origFSM.getTransitions ( ) )
+		res.addTransition ( statePermutationMap.find ( transition.first.first )->second, transition.first.second, statePermutationMap.find ( transition.second )->second );
 
 	return res;
 }
diff --git a/alib2algo/src/automaton/properties/AllEpsilonClosure.h b/alib2algo/src/automaton/properties/AllEpsilonClosure.h
index 4be71a1226..9e6a851b8d 100644
--- a/alib2algo/src/automaton/properties/AllEpsilonClosure.h
+++ b/alib2algo/src/automaton/properties/AllEpsilonClosure.h
@@ -145,9 +145,8 @@ ext::map<StateType, ext::set<StateType>> AllEpsilonClosure::allEpsilonClosure( c
 
 		for( const std::pair<const StateType, ext::set<StateType>> & p : Qi.at( i - 1 ) )
 			for(const StateType& pclosure : p.second )
-				for(const auto& transition : fsm.getEpsilonTransitionsFromState(pclosure)) {
-					Qi.at( i )[p.first].insert(transition.second.begin(), transition.second.end());
-				}
+				for(const auto& transition : fsm.getEpsilonTransitionsFromState(pclosure))
+					Qi.at( i )[p.first].insert(transition.second);
 
 		if( Qi.at( i ) == Qi.at( i - 1 ) )
 			break;
diff --git a/alib2algo/src/automaton/properties/EpsilonClosure.h b/alib2algo/src/automaton/properties/EpsilonClosure.h
index 4f8e21138d..dffce792e6 100644
--- a/alib2algo/src/automaton/properties/EpsilonClosure.h
+++ b/alib2algo/src/automaton/properties/EpsilonClosure.h
@@ -151,12 +151,13 @@ ext::set<StateType> EpsilonClosure::epsilonClosure( const automaton::EpsilonNFA
 		visited[ p ] = true;
 		closure.insert( p );
 
-		auto tos = fsm.getTransitions( ).find(ext::make_pair ( p, ext::variant < EpsilonType, SymbolType >::template from < EpsilonType > ( ) ) );
-		if(tos == fsm.getTransitions().end()) continue;
+		auto tos = fsm.getTransitions( ).equal_range(ext::make_pair ( p, ext::variant < EpsilonType, SymbolType >::template from < EpsilonType > ( ) ) );
+		if ( tos.empty ( ) )
+			continue;
 
-		for( const auto & to : tos->second )
-			if( visited [ to ] == false )
-				queue.push( to );
+		for( const auto & transition : tos )
+			if( visited [ transition.second ] == false )
+				queue.push( transition.second );
 	}
 
 	return closure;
diff --git a/alib2algo/src/automaton/properties/ReachableStates.h b/alib2algo/src/automaton/properties/ReachableStates.h
index 96c81bf68c..cac879d6dc 100644
--- a/alib2algo/src/automaton/properties/ReachableStates.h
+++ b/alib2algo/src/automaton/properties/ReachableStates.h
@@ -74,6 +74,20 @@ public:
 	template < class SymbolType, class StateType >
 	static ext::set<StateType> reachableStates( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm );
 
+	/**
+	 * Finds all reachable states of a nondeterministic finite automaton.
+	 * Using closure implementation of the BFS algorithm.
+	 *
+	 * @overload
+	 *
+	 * @tparam SymbolType Type for the input symbols.
+	 * @tparam StateType Type for the states.
+	 * @param fsm nondeterministic finite automaton
+	 * @return set of reachable states from the initial state of @p fsm
+	 */
+	template < class SymbolType, class EpsilonType, class StateType >
+	static ext::set<StateType> reachableStates( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm );
+
 	/**
 	 * Finds all reachable states of a nondeterministic finite automaton.
 	 * Using closure implementation of the BFS algorithm.
@@ -185,6 +199,32 @@ ext::set<StateType> ReachableStates::reachableStates( const automaton::MultiInit
 	return Qi.at( i );
 }
 
+template < class SymbolType, class EpsilonType, class StateType >
+ext::set<StateType> ReachableStates::reachableStates( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm ) {
+	// 1a
+	ext::deque<ext::set<StateType>> Qi;
+	Qi.push_back( ext::set<StateType>( ) );
+	Qi.at( 0 ). insert( fsm.getInitialState( ) );
+
+	int i = 1;
+
+	// 1bc
+	while( true ) {
+		Qi.push_back( Qi.at( i - 1 ) );
+
+		for( const auto & p : Qi.at( i - 1 ) )
+			for( const auto & transition : fsm.getTransitionsFromState( p ) )
+				Qi.at( i ).insert( transition.second );
+
+		if( Qi.at( i ) == Qi.at( i - 1 ) )
+			break;
+
+		i = i + 1;
+	}
+
+	return Qi.at( i );
+}
+
 template < class SymbolType, class StateType >
 ext::set<StateType> ReachableStates::reachableStates( const automaton::NFA < SymbolType, StateType > & fsm ) {
 	// 1a
diff --git a/alib2algo/src/automaton/run/Run.h b/alib2algo/src/automaton/run/Run.h
index e2cfd634a7..86a44ff88c 100644
--- a/alib2algo/src/automaton/run/Run.h
+++ b/alib2algo/src/automaton/run/Run.h
@@ -379,11 +379,12 @@ ext::tuple < bool, ext::set < StateType >, ext::set < unsigned > > Run::calculat
 		ext::set < StateType > next;
 
 		for ( const StateType & state : states ) {
-			auto transitions = automaton.getTransitions ( ).find ( ext::make_pair ( state, ext::variant < EpsilonType, SymbolType > ( symbol ) ) );
+			auto transitions = automaton.getTransitions ( ).equal_range ( ext::make_pair ( state, ext::variant < EpsilonType, SymbolType > ( symbol ) ) );
 
-			if ( transitions == automaton.getTransitions ( ).end ( ) ) continue;
+			if ( transitions.empty ( ) ) continue;
 
-			next.insert ( transitions->second.begin ( ), transitions->second.end ( ) );
+			for ( const auto & transition : transitions )
+				next.insert ( transition.second );
 		}
 
 		ext::set < StateType > epsilonNext;
diff --git a/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.h b/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.h
index ad84682d41..15b51b38e2 100644
--- a/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.h
+++ b/alib2algo/src/automaton/simplify/EpsilonRemoverIncoming.h
@@ -101,7 +101,7 @@ automaton::NFA < SymbolType, StateType > EpsilonRemoverIncoming::remove( const a
 	fsm.setStates( origFSM.getStates() );
 	fsm.setInputAlphabet( origFSM.getInputAlphabet() );
 
-	ext::map<ext::pair<StateType, SymbolType>, ext::set<StateType>> origTransitions = origFSM.getSymbolTransitions();
+	ext::multimap < ext::pair < StateType, SymbolType >, StateType > origTransitions = origFSM.getSymbolTransitions();
 
 	/**
 	 * Step 1 from Melichar 2.41
@@ -109,11 +109,11 @@ automaton::NFA < SymbolType, StateType > EpsilonRemoverIncoming::remove( const a
 	for( const auto & from : origFSM.getStates( ) )
 		for( const auto & fromClosure : automaton::properties::EpsilonClosure::epsilonClosure( origFSM, from ) )
 			for( const auto & symbol : origFSM.getInputAlphabet() ) {
-				auto transitions = origTransitions.find(ext::make_pair(fromClosure, symbol));
-				if(transitions == origTransitions.end()) continue;
+				auto transitions = origTransitions.equal_range(ext::make_pair(fromClosure, symbol));
+				if(transitions.empty ( ) ) continue;
 
-				for( const auto & to : transitions->second )
-					fsm.addTransition( from, symbol, to );
+				for( const auto & transition : transitions )
+					fsm.addTransition( from, symbol, transition.second );
 			}
 
 	/**
diff --git a/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.h b/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.h
index eaf6006268..d3619e3f80 100644
--- a/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.h
+++ b/alib2algo/src/automaton/simplify/EpsilonRemoverOutgoing.h
@@ -110,7 +110,7 @@ automaton::MultiInitialStateNFA < SymbolType, StateType > EpsilonRemoverOutgoing
 
 		for( const auto & symbol : origFSM.getInputAlphabet() ) {
 			for( const auto& transition : origFSM.getTransitions( ) ) {
-				if(transition.second.find(middle) == transition.second.end()) continue;
+				if(transition.second == middle ) continue;
 				if(transition.first.second != symbol) continue;
 
 				for( const auto & to : middleClosure )
diff --git a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h
index 943e853256..f68721155d 100644
--- a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h
+++ b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h
@@ -63,6 +63,14 @@ public:
 	template < class T >
 	static T remove( const T & automaton );
 
+	/**
+	 * @overload
+	 * @tparam SymbolType Type for input symbols.
+	 * @tparam StateType Type for states.
+	 */
+	template < class SymbolType, class EpsilonType, class StateType >
+	static automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > remove( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm );
+
 	/**
 	 * @overload
 	 * @tparam SymbolType Type for input symbols.
@@ -149,6 +157,32 @@ T UnreachableStatesRemover::remove ( const T & fsm ) {
 	return M;
 }
 
+template < class SymbolType, class EpsilonType, class StateType >
+automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > UnreachableStatesRemover::remove( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm ) {
+	// 1a
+	ext::set<StateType> Qa = automaton::properties::ReachableStates::reachableStates( fsm );
+
+	// 2
+	automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > 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 );
+
+	ext::set<StateType> 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 < class SymbolType, class StateType >
 automaton::NFA < SymbolType, StateType > UnreachableStatesRemover::remove( const automaton::NFA < SymbolType, StateType > & fsm ) {
 	// 1a
diff --git a/alib2algo/src/automaton/simplify/UselessStatesRemover.h b/alib2algo/src/automaton/simplify/UselessStatesRemover.h
index 168eeb7c0f..b6810fd5e1 100644
--- a/alib2algo/src/automaton/simplify/UselessStatesRemover.h
+++ b/alib2algo/src/automaton/simplify/UselessStatesRemover.h
@@ -59,6 +59,14 @@ public:
 	template < class T >
 	static T remove( const T & automaton );
 
+	/**
+	 * @overload
+	 * @tparam SymbolType Type for input symbols.
+	 * @tparam StateType Type for states.
+	 */
+	template < class SymbolType, class EpsilonType, class StateType >
+	static automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > remove( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm );
+
 	/**
 	 * @overload
 	 * @tparam SymbolType Type for input symbols.
@@ -141,6 +149,34 @@ T UselessStatesRemover::remove( const T & fsm ) {
 	return M;
 }
 
+template < class SymbolType, class EpsilonType, class StateType >
+automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > UselessStatesRemover::remove( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm ) {
+	// 1.
+	ext::set<StateType> Qu = automaton::properties::UsefulStates::usefulStates( fsm );
+
+	// 2.
+	automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > 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 < class SymbolType, class StateType >
 automaton::NFA < SymbolType, StateType > UselessStatesRemover::remove( const automaton::NFA < SymbolType, StateType > & fsm ) {
 	// 1.
diff --git a/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h b/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h
index 33daa73c1f..b32a4e0396 100644
--- a/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h
+++ b/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h
@@ -141,12 +141,10 @@ automaton::EpsilonNFA < SymbolType, EpsilonType, ext::pair < StateType, unsigned
 		res.addFinalState ( ext::make_pair ( q, secondDefault ) );
 
 	for ( const auto & t : first.getTransitions ( ) )
-		for ( const StateType & q : t.second )
-			res.addTransition ( ext::make_pair ( t.first.first, firstDefault ), t.first.second, ext::make_pair ( q, firstDefault ) );
+		res.addTransition ( ext::make_pair ( t.first.first, firstDefault ), t.first.second, ext::make_pair ( t.second, firstDefault ) );
 
 	for ( const auto & t : second.getTransitions ( ) )
-		for ( const StateType & q : t.second )
-			res.addTransition ( ext::make_pair ( t.first.first, secondDefault ), t.first.second, ext::make_pair ( q, secondDefault ) );
+		res.addTransition ( ext::make_pair ( t.first.first, secondDefault ), t.first.second, ext::make_pair ( t.second, secondDefault ) );
 
 	for ( const StateType & q : first.getFinalStates ( ) )
 		res.addTransition ( ext::make_pair ( q, firstDefault ), ext::make_pair ( second.getInitialState ( ), secondDefault ) );
diff --git a/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h
index bca0bab6cb..e99aa1d7bd 100644
--- a/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h
+++ b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h
@@ -90,12 +90,10 @@ automaton::EpsilonNFA < SymbolType, EpsilonType, ext::pair < StateType, unsigned
 	res.addTransition ( q0, ext::make_pair ( second.getInitialState ( ), secondDefault ) );
 
 	for(const auto& t : first.getTransitions())
-		for(const auto& q : t.second)
-			res.addTransition ( ext::make_pair ( t.first.first, firstDefault ), t.first.second, ext::make_pair ( q, firstDefault ) );
+		res.addTransition ( ext::make_pair ( t.first.first, firstDefault ), t.first.second, ext::make_pair ( t.second, firstDefault ) );
 
 	for(const auto& t : second.getTransitions())
-		for(const auto& q : t.second)
-			res.addTransition ( ext::make_pair ( t.first.first, secondDefault ), t.first.second, ext::make_pair ( q, secondDefault ) );
+		res.addTransition ( ext::make_pair ( t.first.first, secondDefault ), t.first.second, ext::make_pair ( t.second, secondDefault ) );
 
 	return res;
 }
diff --git a/alib2aux/src/convert/DotConverter.h b/alib2aux/src/convert/DotConverter.h
index 490df13249..b5ec4af8ba 100644
--- a/alib2aux/src/convert/DotConverter.h
+++ b/alib2aux/src/convert/DotConverter.h
@@ -789,22 +789,20 @@ void DotConverter::transitions(const automaton::EpsilonNFA < SymbolType, Epsilon
 			symbol = replace ( factory::StringDataFactory::toString ( std::get<1>(transition.first ).template get<SymbolType>()), "\"", "\\\"" );
 		}
 
-		for(const StateType& to : transition.second) {
-			std::pair<int, int> key(states.find(transition.first.first)->second, states.find(to)->second);
-			ext::map<std::pair<int, int>, std::string>::iterator mapit = transitions.find(key);
+		std::pair<int, int> key(states.find(transition.first.first)->second, states.find(transition.second)->second);
+		ext::map<std::pair<int, int>, std::string>::iterator mapit = transitions.find(key);
 
-			if (mapit == transitions.end()) {
-				transitions.insert(std::make_pair(key, symbol));
-			} else {
-				mapit->second += ",";
+		if (mapit == transitions.end()) {
+			transitions.insert(std::make_pair(key, symbol));
+		} else {
+			mapit->second += ",";
 
-				size_t pos = mapit->second.find_last_of("\n");
-				if(pos == std::string::npos) pos = 0;
-				if(mapit->second.size() - pos > 100) mapit->second += "\n";
-				else mapit->second += " ";
+			size_t pos = mapit->second.find_last_of("\n");
+			if(pos == std::string::npos) pos = 0;
+			if(mapit->second.size() - pos > 100) mapit->second += "\n";
+			else mapit->second += " ";
 
-				mapit->second += symbol;
-			}
+			mapit->second += symbol;
 		}
 	}
 
diff --git a/alib2aux/src/convert/GasTexConverter.h b/alib2aux/src/convert/GasTexConverter.h
index 9b6e108d8d..57d3324fab 100644
--- a/alib2aux/src/convert/GasTexConverter.h
+++ b/alib2aux/src/convert/GasTexConverter.h
@@ -885,22 +885,20 @@ template<class SymbolType, class EpsilonType, class StateType>
 void GasTexConverter::transitions(const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm, std::ostream& out) {
 	ext::map<std::pair<std::string, std::string>, std::string> transitionMap;
 	for (const auto& transition : fsm.getTransitions()) {
-		for(const auto& to : transition.second) {
-			std::pair<std::string, std::string> key(replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( to ), "\"", "\\\"" ) );
+		std::pair<std::string, std::string> key(replace ( factory::StringDataFactory::toString ( transition.first.first ), "\"", "\\\"" ), replace ( factory::StringDataFactory::toString ( transition.second ), "\"", "\\\"" ) );
 
-			std::string symbol;
-			if (transition.first.second.template is<EpsilonType>()) {
-				symbol = "$\\varepsilon$";
-			} else {
-				symbol = replace ( factory::StringDataFactory::toString ( transition.first.second.template get<SymbolType>( ) ), "\"", "\\\"" );
-			}
+		std::string symbol;
+		if (transition.first.second.template is<EpsilonType>()) {
+			symbol = "$\\varepsilon$";
+		} else {
+			symbol = replace ( factory::StringDataFactory::toString ( transition.first.second.template get<SymbolType>( ) ), "\"", "\\\"" );
+		}
 
-			auto mapIterator = transitionMap.find(key);
-			if (mapIterator == transitionMap.end()) {
-				transitionMap.insert(make_pair(key, symbol));
-			} else {
-				mapIterator->second += ", " + symbol;
-			}
+		auto mapIterator = transitionMap.find(key);
+		if (mapIterator == transitionMap.end()) {
+			transitionMap.insert(make_pair(key, symbol));
+		} else {
+			mapIterator->second += ", " + symbol;
 		}
 	}
 	printTransitionMap(transitionMap, out);
diff --git a/alib2aux/src/convert/TikZConverter.h b/alib2aux/src/convert/TikZConverter.h
index 329695a7ea..bb13e2937f 100644
--- a/alib2aux/src/convert/TikZConverter.h
+++ b/alib2aux/src/convert/TikZConverter.h
@@ -734,26 +734,24 @@ void TikZConverter::transitions ( const automaton::EpsilonNFA < SymbolType, Epsi
 		else
 			symbol = replace ( factory::StringDataFactory::toString (  std::get < 1 > ( transition.first  ).template get < SymbolType > ( ) ), "\"", "\\\"" );
 
-		for ( const StateType & to : transition.second ) {
-			std::pair < int, int > key ( states.find ( transition.first.first )->second, states.find ( to )->second );
-			ext::map < std::pair < int, int >, std::string >::iterator mapit = transitions.find ( key );
+		std::pair < int, int > key ( states.find ( transition.first.first )->second, states.find ( transition.second )->second );
+		ext::map < std::pair < int, int >, std::string >::iterator mapit = transitions.find ( key );
 
-			if ( mapit == transitions.end ( ) ) {
-				transitions.insert ( std::make_pair ( key, symbol ) );
-			} else {
-				mapit->second += ",";
+		if ( mapit == transitions.end ( ) ) {
+			transitions.insert ( std::make_pair ( key, symbol ) );
+		} else {
+			mapit->second += ",";
 
-				size_t pos = mapit->second.find_last_of ( "\n" );
+			size_t pos = mapit->second.find_last_of ( "\n" );
 
-				if ( pos == std::string::npos ) pos = 0;
+			if ( pos == std::string::npos ) pos = 0;
 
-				if ( mapit->second.size ( ) - pos > 100 )
-					mapit->second += "\n";
-				else
-					mapit->second += " ";
+			if ( mapit->second.size ( ) - pos > 100 )
+				mapit->second += "\n";
+			else
+				mapit->second += " ";
 
-				mapit->second += symbol;
-			}
+			mapit->second += symbol;
 		}
 	}
 
diff --git a/alib2data/src/automaton/FSM/CompactNFA.h b/alib2data/src/automaton/FSM/CompactNFA.h
index 87b45b1d08..5c01a3e8cc 100644
--- a/alib2data/src/automaton/FSM/CompactNFA.h
+++ b/alib2data/src/automaton/FSM/CompactNFA.h
@@ -467,9 +467,9 @@ template < class EpsilonType >
 CompactNFA < SymbolType, StateType >::CompactNFA ( const EpsilonNFA < SymbolType, EpsilonType, StateType > & other ) : CompactNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
 	for ( const auto & transition : other.getTransitions ( ) )
 		if ( transition.first.second.template is < EpsilonType > ( ) )
-			transitions.insert ( ext::make_pair ( transition.first.first, ext::vector < SymbolType > { } ), transition.second );
+			transitions [ ext::make_pair ( transition.first.first, ext::vector < SymbolType > { } ) ].insert ( transition.second );
 		else
-			transitions.insert ( ext::make_pair ( transition.first.first, ext::vector < SymbolType > { transition.first.second.template get < SymbolType > ( ) } ), transition.second );
+			transitions [ ext::make_pair ( transition.first.first, ext::vector < SymbolType > { transition.first.second.template get < SymbolType > ( ) } ) ].insert ( transition.second );
 }
 
 template < class SymbolType, class StateType >
diff --git a/alib2data/src/automaton/FSM/EpsilonNFA.h b/alib2data/src/automaton/FSM/EpsilonNFA.h
index dd0b4eb113..47dbf65d03 100644
--- a/alib2data/src/automaton/FSM/EpsilonNFA.h
+++ b/alib2data/src/automaton/FSM/EpsilonNFA.h
@@ -27,7 +27,7 @@
 #include <ostream>
 #include <sstream>
 
-#include <alib/map>
+#include <alib/multimap>
 #include <alib/set>
 #include <alib/variant>
 
@@ -79,7 +79,7 @@ class EpsilonNFA final : public ext::CompareOperators < EpsilonNFA < SymbolType,
 	/**
 	 * Transition function as mapping from a state times an input symbol or epsilon on the left hand side to a set of states.
 	 */
-	ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > transitions;
+	ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > transitions;
 
 public:
 	/**
@@ -350,42 +350,19 @@ public:
 	bool addTransition ( StateType from, StateType to );
 
 	/**
-	 * \brief Add a transitions to the automaton.
+	 * \brief Removes a transition to the automaton.
 	 *
-	 * \details The transition is in a form A \times a -> P(Q), where A \in Q, a \in T \cup \{\epsilon\}, P(Q) is a powerset of states.
+	 * \details The transition is in a form A \times a -> B, where A, B \in Q and a \in T \cup \{\epsilon\}
 	 *
 	 * \param current the source state (A)
 	 * \param input the input symbol or epsilon (a)
-	 * \param next the target states (P(Q))
-	 *
-	 * \throws AutomatonException when transitions contain states or symbols not present in the automaton components
-	 */
-	void addTransitions ( StateType from, ext::variant < EpsilonType, SymbolType > input, ext::set < StateType > to );
-
-	/**
-	 * \brief Add a transitions to the automaton.
-	 *
-	 * \details The transition is in a form A \times a -> P(Q), where A \in Q, a \in T, P(Q) is a powerset of states.
-	 *
-	 * \param current the source state (A)
-	 * \param input the input symbol (a)
-	 * \param next the target states (P(Q))
-	 *
-	 * \throws AutomatonException when transitions contain states or symbols not present in the automaton components
-	 */
-	void addTransitions ( StateType from, SymbolType input, ext::set < StateType > to );
-
-	/**
-	 * \brief Add a transitions to the automaton.
-	 *
-	 * \details The transition is in a form A \times \epsilon -> P(Q), where A \in Q, P(Q) is a powerset of states.
+	 * \param next the target state (B)
 	 *
-	 * \param current the source state (A)
-	 * \param next the target states (P(Q))
+	 * \throws AutomatonException when transition contains state or symbol not present in the automaton components
 	 *
-	 * \throws AutomatonException when transitions contain states or symbols not present in the automaton components
+	 * \returns true if the transition was indeed added
 	 */
-	void addTransitions ( StateType from, ext::set < StateType > to );
+	bool removeTransition ( StateType from, ext::variant < EpsilonType, SymbolType > input, StateType to );
 
 	/**
 	 * \brief Removes a transition from the automaton.
@@ -417,28 +394,28 @@ public:
 	 *
 	 * \returns transition function of the automaton
 	 */
-	const ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & getTransitions ( ) const &;
+	const ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & getTransitions ( ) const &;
 
 	/**
 	 * Get the transition function of the automaton in its natural form.
 	 *
 	 * \returns transition function of the automaton
 	 */
-	ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > && getTransitions ( ) &&;
+	ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > && getTransitions ( ) &&;
 
 	/**
 	 * Get the epsilon transitions of the automaton
 	 *
 	 * \returns epsilon transitions of the automaton
 	 */
-	ext::map < StateType, ext::set < StateType > > getEpsilonTransitions ( ) const;
+	ext::multimap < StateType, StateType > getEpsilonTransitions ( ) const;
 
 	/**
 	 * Get the non-epsilon transitions of the automaton
 	 *
 	 * \returns non-epsilon transitions of the automaton
 	 */
-	ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > getSymbolTransitions ( ) const;
+	ext::multimap < ext::pair < StateType, SymbolType >, StateType > getSymbolTransitions ( ) const;
 
 	/**
 	 * Get a subset of the transition function of the automaton, with the source state fixed in the transitions natural representation.
@@ -447,7 +424,7 @@ public:
 	 *
 	 * \returns a subset of the transition function of the automaton with the source state fixed
 	 */
-	ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > getTransitionsFromState ( const StateType & from ) const;
+	ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > getTransitionsFromState ( const StateType & from ) const;
 
 	/**
 	 * Get a subset of epsilon transitions of the automaton, with the source state fixed in the transitions natural representation.
@@ -456,7 +433,7 @@ public:
 	 *
 	 * \returns a subset of epsilon transitions of the automaton with the source state fixed
 	 */
-	ext::map < StateType, ext::set < StateType > > getEpsilonTransitionsFromState ( const StateType & from ) const;
+	ext::multimap < StateType, StateType > getEpsilonTransitionsFromState ( const StateType & from ) const;
 
 	/**
 	 * Get a subset of non-epsilon transitions of the automaton, with the source state fixed in the transitions natural representation.
@@ -465,7 +442,7 @@ public:
 	 *
 	 * \returns a subset of non-epsilon transitions of the automaton with the source state fixed
 	 */
-	ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > getSymbolTransitionsFromState ( const StateType & from ) const;
+	ext::multimap < ext::pair < StateType, SymbolType >, StateType > getSymbolTransitionsFromState ( const StateType & from ) const;
 
 	/**
 	 * Get a subset of the transition function of the automaton, with the target state fixed in the transitions natural representation.
@@ -474,7 +451,7 @@ public:
 	 *
 	 * \returns a subset of the transition function of the automaton with the target state fixed
 	 */
-	ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > getTransitionsToState ( const StateType & from ) const;
+	ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > getTransitionsToState ( const StateType & from ) const;
 
 	/**
 	 * Get a subset of epsilon transitions of the automaton, with the target state fixed in the transitions natural representation.
@@ -483,7 +460,7 @@ public:
 	 *
 	 * \returns a subset of epsilon transitions of the automaton with the target state fixed
 	 */
-	ext::map < StateType, ext::set < StateType > > getEpsilonTransitionsToState ( const StateType & to ) const;
+	ext::multimap < StateType, StateType > getEpsilonTransitionsToState ( const StateType & to ) const;
 
 	/**
 	 * Get a subset of non-epsilon transitions of the automaton, with the target state fixed in the transitions natural representation.
@@ -492,7 +469,7 @@ public:
 	 *
 	 * \returns a subset of non-epsilon transitions of the automaton with the target state fixed
 	 */
-	ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > getSymbolTransitionsToState ( const StateType & to ) const;
+	ext::multimap < ext::pair < StateType, SymbolType >, StateType > getSymbolTransitionsToState ( const StateType & to ) const;
 
 	/**
 	 * \brief Determines whether the automaton is without epsilon transitions.
@@ -570,22 +547,24 @@ EpsilonNFA < SymbolType, EpsilonType, StateType >::EpsilonNFA ( StateType initia
 template<class SymbolType, class EpsilonType, class StateType >
 EpsilonNFA < SymbolType, EpsilonType, StateType >::EpsilonNFA ( const MultiInitialStateNFA < SymbolType, StateType > & other ) : EpsilonNFA ( other.getStates ( ) + ext::set < StateType > { common::createUnique ( label::InitialStateLabel::instance < StateType > ( ), other.getStates ( ) ) }, other.getInputAlphabet ( ), common::createUnique ( label::InitialStateLabel::instance < StateType > ( ), other.getStates ( ) ), other.getFinalStates ( ) ) {
 	for ( const auto & transition : other.getTransitions ( ) )
-		transitions.insert ( ext::make_pair ( transition.first.first, ext::variant < EpsilonType, SymbolType > ( transition.first.second ) ), transition.second );
+		for ( const auto & toState : transition.second )
+			transitions.insert ( ext::make_pair ( transition.first.first, ext::variant < EpsilonType, SymbolType > ( transition.first.second ) ), toState );
 
-	transitions.insert ( ext::make_pair ( getInitialState ( ), ext::variant < EpsilonType, SymbolType >::template from < EpsilonType > ( ) ), other.getInitialStates ( ) );
+	for ( const auto & initialState : other.getInitialStates ( ) )
+		transitions.insert ( ext::make_pair ( getInitialState ( ), ext::variant < EpsilonType, SymbolType >::template from < EpsilonType > ( ) ), initialState );
 }
 
 
 template<class SymbolType, class EpsilonType, class StateType >
 EpsilonNFA < SymbolType, EpsilonType, StateType >::EpsilonNFA ( const NFA < SymbolType, StateType > & other ) : EpsilonNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
 	for ( const auto & transition : other.getTransitions ( ) )
-		transitions [ ext::make_pair ( transition.first.first, ext::variant < EpsilonType, SymbolType > ( transition.first.second ) ) ].insert ( transition.second );
+		transitions.insert ( ext::make_pair ( transition.first.first, ext::variant < EpsilonType, SymbolType > ( transition.first.second ) ), transition.second );
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
 EpsilonNFA < SymbolType, EpsilonType, StateType >::EpsilonNFA ( const DFA < SymbolType, StateType > & other ) : EpsilonNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
 	for ( const auto & transition : other.getTransitions ( ) )
-		transitions [ ext::make_pair ( transition.first.first, ext::variant < EpsilonType, SymbolType > ( transition.first.second ) ) ].insert ( transition.second );
+		transitions.insert ( ext::make_pair ( transition.first.first, ext::variant < EpsilonType, SymbolType > ( transition.first.second ) ), transition.second );
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
@@ -593,15 +572,21 @@ bool EpsilonNFA < SymbolType, EpsilonType, StateType >::addTransition ( StateTyp
 	if ( !getStates ( ).count ( from ) )
 		throw AutomatonException ( "State \"" + ext::to_string ( from ) + "\" doesn't exist." );
 
-	if ( input.template is < SymbolType > ( ) && !getInputAlphabet ( ).count ( input.template get < SymbolType > ( ) ) )
+	if ( ! input.template is < EpsilonType > ( ) && !getInputAlphabet ( ).count ( input ) )
 		throw AutomatonException ( "Input symbol \"" + ext::to_string ( input ) + "\" doesn't exist." );
 
 	if ( !getStates ( ).count ( to ) )
 		throw AutomatonException ( "State \"" + ext::to_string ( to ) + "\" doesn't exist." );
 
-	ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key = ext::make_pair ( std::move ( from ), std::move ( input ) );
+	auto upper_bound = transitions.upper_bound ( ext::tie ( from, input ) );
+	auto lower_bound = transitions.lower_bound ( ext::tie ( from, input ) );
+	auto iter = std::lower_bound ( lower_bound, upper_bound, to, [ ] ( const auto & transition, const auto & target ) { return transition.second < target; } );
+	if ( iter != upper_bound && to >= iter->second )
+		return false;
 
-	return transitions[std::move ( key )].insert ( std::move ( to ) ).second;
+	ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key = ext::make_pair ( std::move ( from ), std::move ( input ) );
+	transitions.insert ( iter, std::make_pair ( std::move ( key ), std::move ( to ) ) );
+	return true;
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
@@ -618,173 +603,150 @@ bool EpsilonNFA < SymbolType, EpsilonType, StateType >::addTransition ( StateTyp
 	return addTransition ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) );
 }
 
-template < class SymbolType, class EpsilonType, class StateType >
-void EpsilonNFA < SymbolType, EpsilonType, StateType >::addTransitions ( StateType from, ext::variant < EpsilonType, SymbolType > input, ext::set < StateType > to ) {
-	if ( !getStates ( ).count ( from ) )
-		throw AutomatonException ( "State \"" + ext::to_string ( from ) + "\" doesn't exist." );
-
-	if ( input.template is < SymbolType > ( ) && !getInputAlphabet ( ).count ( input.template get < SymbolType > ( ) ) )
-		throw AutomatonException ( "Input symbol \"" + ext::to_string ( input ) + "\" doesn't exist." );
-
-	if ( !std::includes ( getStates ( ).begin ( ), getStates ( ).end ( ), to.begin ( ), to.end ( ) ) )
-		throw AutomatonException ( "Some target states don't exist." );
-
-	ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key = ext::make_pair ( std::move ( from ), std::move ( input ) );
-
-	transitions [ std::move ( key ) ].insert ( ext::make_mover ( to ).begin ( ), ext::make_mover ( to ).end ( ) );
-}
-
 template<class SymbolType, class EpsilonType, class StateType >
-void EpsilonNFA < SymbolType, EpsilonType, StateType >::addTransitions ( StateType from, SymbolType input, ext::set < StateType > to ) {
-	ext::variant < EpsilonType, SymbolType > inputVariant ( std::move ( input ) );
-
-	addTransitions ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) );
-}
-
-template<class SymbolType, class EpsilonType, class StateType >
-void EpsilonNFA < SymbolType, EpsilonType, StateType >::addTransitions ( StateType from, ext::set < StateType > to ) {
-	auto inputVariant = ext::variant < EpsilonType, SymbolType >::template from < EpsilonType > ( );
+bool EpsilonNFA < SymbolType, EpsilonType, StateType >::removeTransition ( StateType from, ext::variant < EpsilonType, SymbolType > input, StateType to ) {
+	auto upper_bound = transitions.upper_bound ( ext::tie ( from, input ) );
+	auto lower_bound = transitions.lower_bound ( ext::tie ( from, input ) );
+	auto iter = std::find_if ( lower_bound, upper_bound, [ & ] ( const auto & transition ) { return transition.second == to; } );
+	if ( iter == upper_bound )
+		return false;
 
-	addTransitions ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) );
+	transitions.erase ( iter );
+	return true;
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
 bool EpsilonNFA < SymbolType, EpsilonType, StateType >::removeTransition ( const StateType & from, const SymbolType & input, const StateType & to ) {
-	ext::variant < EpsilonType, SymbolType > inputVariant ( input );
-	ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key = ext::make_pair ( from, inputVariant );
+	ext::variant < EpsilonType, SymbolType > inputVariant ( std::move ( input ) );
 
-	return transitions[key].erase ( to );
+	return addTransition ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) );
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
 bool EpsilonNFA < SymbolType, EpsilonType, StateType >::removeTransition ( const StateType & from, const StateType & to ) {
 	auto inputVariant = ext::variant < EpsilonType, SymbolType >::template from < EpsilonType > ( );
 
-	ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key = ext::make_pair ( from, inputVariant );
-
-	return transitions[key].erase ( to );
+	return addTransition ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) );
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
-const ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & EpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitions ( ) const & {
+const ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & EpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitions ( ) const & {
 	return transitions;
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
-ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > && EpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitions ( ) && {
+ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > && EpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitions ( ) && {
 	return std::move ( transitions );
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
-ext::map < StateType, ext::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitions ( ) const {
-	ext::map < StateType, ext::set < StateType > > result;
+ext::multimap < StateType, StateType > EpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitions ( ) const {
+	ext::multimap < StateType, StateType > result;
 
-	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions )
+	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & transition : transitions )
 		if ( transition.first.second.template is < EpsilonType > ( ) )
-			result[transition.first.first].insert ( transition.second.begin ( ), transition.second.end ( ) );
+			result.insert ( transition.first.first, transition.second );
 
 	return result;
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
-ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitions ( ) const {
-	ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > result;
+ext::multimap < ext::pair < StateType, SymbolType >, StateType > EpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitions ( ) const {
+	ext::multimap < ext::pair < StateType, SymbolType >, StateType > result;
 
-	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions )
+	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & transition : transitions )
 		if ( transition.first.second.template is < SymbolType > ( ) )
-			result[ext::pair < StateType, SymbolType > ( transition.first.first, transition.first.second.template get < SymbolType > ( ) )].insert ( transition.second.begin ( ), transition.second.end ( ) );
+			result.insert ( ext::make_pair ( transition.first.first, transition.first.second.template get < SymbolType > ( ) ), transition.second );
 
 	return result;
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
-ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitionsFromState ( const StateType & from ) const {
+ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > EpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitionsFromState ( const StateType & from ) const {
 	if ( !getStates ( ).count ( from ) )
 		throw AutomatonException ( "State \"" + ext::to_string ( from ) + "\" doesn't exist" );
 
-	ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > transitionsFromState;
+	ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > transitionsFromState;
 
-	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions )
+	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & transition : transitions )
 		if ( transition.first.first == from )
-			transitionsFromState[transition.first].insert ( transition.second.begin ( ), transition.second.end ( ) );
+			transitionsFromState.insert ( transition );
 
 	return transitionsFromState;
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
-ext::map < StateType, ext::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitionsFromState ( const StateType & from ) const {
+ext::multimap < StateType, StateType > EpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitionsFromState ( const StateType & from ) const {
 	if ( !getStates ( ).count ( from ) )
 		throw AutomatonException ( "State \"" + ext::to_string ( from ) + "\" doesn't exist" );
 
 	ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key ( from, ext::variant < EpsilonType, SymbolType >::template from < EpsilonType > ( ) );
-	ext::map < StateType, ext::set < StateType > > res;
-	auto transition = transitions.find ( key );
-
-	if ( transition != transitions.end ( ) )
-		res.insert ( from, transition->second );
+	ext::multimap < StateType, StateType > res;
+	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & transition : transitions.equal_range ( key ) )
+		res.insert ( transition.first.first, transition.second );
 
 	return res;
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
-ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitionsFromState ( const StateType & from ) const {
+ext::multimap < ext::pair < StateType, SymbolType >, StateType > EpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitionsFromState ( const StateType & from ) const {
 	if ( !getStates ( ).count ( from ) )
 		throw AutomatonException ( "State \"" + ext::to_string ( from ) + "\" doesn't exist" );
 
-	ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > transitionsFromState;
+	ext::multimap < ext::pair < StateType, SymbolType >, StateType > transitionsFromState;
 
-	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions )
+	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & transition : transitions )
 		if ( ( transition.first.first == from ) && transition.first.second.template is < SymbolType > ( ) )
-			transitionsFromState[ext::pair < StateType, SymbolType > ( transition.first.first, transition.first.second.template get < SymbolType > ( ) )].insert ( transition.second.begin ( ), transition.second.end ( ) );
+			transitionsFromState.insert ( std::make_pair ( ext::make_pair ( transition.first.first, transition.first.second.template get < SymbolType > ( ) ), transition.second ) );
 
 	return transitionsFromState;
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
-ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitionsToState ( const StateType & to ) const {
+ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > EpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitionsToState ( const StateType & to ) const {
 	if ( !getStates ( ).count ( to ) )
 		throw AutomatonException ( "State \"" + ext::to_string ( to ) + "\" doesn't exist" );
 
-	ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > transitionsToState;
+	ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > transitionsToState;
 
-	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions )
-		if ( transition.second.find ( to ) != transition.second.end ( ) )
-			transitionsToState[transition.first].insert ( to );
+	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & transition : transitions )
+		if ( transition.second == to )
+			transitionsToState.insert ( transition );
 
 	return transitionsToState;
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
-ext::map < StateType, ext::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitionsToState ( const StateType & to ) const {
+ext::multimap < StateType, StateType > EpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitionsToState ( const StateType & to ) const {
 	if ( !getStates ( ).count ( to ) )
 		throw AutomatonException ( "State \"" + ext::to_string ( to ) + "\" doesn't exist" );
 
-	ext::map < StateType, ext::set < StateType > > transitionsToState;
+	ext::multimap < StateType, StateType > transitionsToState;
 
-	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions )
-		if ( ( transition.second.find ( to ) != transition.second.end ( ) ) && transition.first.second.template is < EpsilonType > ( ) )
-			transitionsToState[transition.first.first].insert ( to );
+	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & transition : transitions )
+		if ( transition.second == to && transition.first.second.template is < EpsilonType > ( ) )
+			transitionsToState.insert ( transition.first.first, to );
 
 	return transitionsToState;
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
-ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > EpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitionsToState ( const StateType & to ) const {
+ext::multimap < ext::pair < StateType, SymbolType >, StateType > EpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitionsToState ( const StateType & to ) const {
 	if ( !getStates ( ).count ( to ) )
 		throw AutomatonException ( "State \"" + ext::to_string ( to ) + "\" doesn't exist" );
 
-	ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > transitionsToState;
+	ext::multimap < ext::pair < StateType, SymbolType >, StateType > transitionsToState;
 
-	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions )
-		if ( ( transition.second.find ( to ) != transition.second.end ( ) ) && transition.first.second.template is < SymbolType > ( ) )
-			transitionsToState[ext::pair < StateType, SymbolType > ( transition.first.first, transition.first.second.template get < SymbolType > ( ) )].insert ( to );
+	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & transition : transitions )
+		if ( transition.second == to && transition.first.second.template is < SymbolType > ( ) )
+			transitionsToState.insert ( ext::pair < StateType, SymbolType > ( transition.first.first, transition.first.second.template get < SymbolType > ( ) ), to );
 
 	return transitionsToState;
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
 bool EpsilonNFA < SymbolType, EpsilonType, StateType >::isEpsilonFree ( ) const {
-	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions )
+	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & transition : transitions )
 		if ( transition.first.second.template is < EpsilonType > ( ) )
 			return false;
 
@@ -793,8 +755,11 @@ bool EpsilonNFA < SymbolType, EpsilonType, StateType >::isEpsilonFree ( ) const
 
 template<class SymbolType, class EpsilonType, class StateType >
 bool EpsilonNFA < SymbolType, EpsilonType, StateType >::isDeterministic ( ) const {
-	for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions )
-		if ( transition.second.size ( ) > 1 )
+	if ( transitions.empty ( ) )
+		return true;
+
+	for ( auto iter = transitions.begin ( ); std::next ( iter ) != transitions.end ( ); ++ iter )
+		if ( iter->first == std::next ( iter )->first )
 			return false;
 
 	return isEpsilonFree ( );
@@ -845,7 +810,7 @@ public:
 	 * \returns true if the symbol is used, false othervise
 	 */
 	static bool used ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & automaton, const SymbolType & symbol ) {
-		for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : automaton.getTransitions ( ) )
+		for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & transition : automaton.getTransitions ( ) )
 			if ( transition.first.second.template is < SymbolType > ( ) && ( transition.first.second.template get < SymbolType > ( ) == symbol ) )
 				return true;
 
@@ -899,8 +864,8 @@ public:
 		if ( automaton.getFinalStates ( ).count ( state ) )
 			return true;
 
-		for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : automaton.getTransitions ( ) )
-			if ( ( transition.first.first == state ) || transition.second.count ( state ) )
+		for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & transition : automaton.getTransitions ( ) )
+			if ( transition.first.first == state || transition.second == state )
 				return true;
 
 		return false;
@@ -1019,12 +984,12 @@ struct normalize < automaton::EpsilonNFA < SymbolType, EpsilonType, StateType >
 
 		automaton::EpsilonNFA < > res ( std::move ( states ), std::move ( alphabet ), std::move ( initialState ), std::move ( finalStates ) );
 
-		for ( std::pair < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > && transition : ext::make_mover ( std::move ( value ).getTransitions ( ) ) ) {
+		for ( std::pair < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > && transition : ext::make_mover ( std::move ( value ).getTransitions ( ) ) ) {
 			DefaultStateType from = automaton::AutomatonNormalize::normalizeState ( std::move ( transition.first.first ) );
 			ext::variant < DefaultEpsilonType, DefaultSymbolType > input = automaton::AutomatonNormalize::normalizeSymbolEpsilon ( std::move ( transition.first.second ) );
-			ext::set < DefaultStateType > targets = automaton::AutomatonNormalize::normalizeStates ( std::move ( transition.second ) );
+			DefaultStateType target = automaton::AutomatonNormalize::normalizeState ( std::move ( transition.second ) );
 
-			res.addTransitions ( std::move ( from ), std::move ( input ), std::move ( targets ) );
+			res.addTransition ( std::move ( from ), std::move ( input ), std::move ( target ) );
 		}
 
 		return res;
diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.h b/alib2data/src/automaton/FSM/ExtendedNFA.h
index 49f2e64230..23dbea22f7 100644
--- a/alib2data/src/automaton/FSM/ExtendedNFA.h
+++ b/alib2data/src/automaton/FSM/ExtendedNFA.h
@@ -488,10 +488,10 @@ ExtendedNFA < SymbolType, StateType >::ExtendedNFA ( const EpsilonNFA < SymbolTy
 	for ( const auto & transition : other.getTransitions ( ) ) {
 		if ( transition.first.second.template is < EpsilonType > ( ) ) {
 			ext::pair < StateType, regexp::UnboundedRegExpStructure < SymbolType > > key = ext::make_pair ( transition.first.first, regexp::UnboundedRegExpStructure < SymbolType > ( regexp::UnboundedRegExpEpsilon < SymbolType > ( ) ) );
-			transitions[key] = transition.second;
+			transitions[key].insert ( transition.second );
 		} else {
 			ext::pair < StateType, regexp::UnboundedRegExpStructure < SymbolType > > key = ext::make_pair ( transition.first.first, regexp::UnboundedRegExpStructure < SymbolType > ( regexp::UnboundedRegExpSymbol < SymbolType > ( transition.first.second.template get < SymbolType > ( ) ) ) );
-			transitions[key] = transition.second;
+			transitions[key].insert ( transition.second );
 		}
 	}
 }
diff --git a/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h b/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h
index 17f1b01dfe..3bfa3cbe2a 100644
--- a/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h
+++ b/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h
@@ -608,7 +608,7 @@ template<class SymbolType, class EpsilonType, class StateType >
 MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::MultiInitialStateEpsilonNFA ( const EpsilonNFA < SymbolType, EpsilonType, StateType > & other ) : MultiInitialStateEpsilonNFA ( other.getStates ( ), other.getInputAlphabet ( ), { other.getInitialState ( ) }, other.getFinalStates ( ) ) {
 	for ( const auto & transition : other.getTransitions ( ) ) {
 		ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key = ext::make_pair ( transition.first.first, ext::variant < EpsilonType, SymbolType > ( transition.first.second ) );
-		transitions[key] = transition.second;
+		transitions[key].insert ( transition.second );
 	}
 }
 
diff --git a/alib2data/src/automaton/FSM/NFA.h b/alib2data/src/automaton/FSM/NFA.h
index 59c894082a..f26025c801 100644
--- a/alib2data/src/automaton/FSM/NFA.h
+++ b/alib2data/src/automaton/FSM/NFA.h
@@ -422,27 +422,27 @@ bool NFA < SymbolType, StateType >::addTransition ( StateType from, SymbolType i
 	if ( !getStates ( ).count ( to ) )
 		throw AutomatonException ( "State \"" + ext::to_string ( to ) + "\" doesn't exist." );
 
-	ext::pair < StateType, SymbolType > key = ext::make_pair ( std::move ( from ), std::move ( input ) );
-
-	auto upper_bound = transitions.upper_bound ( key );
-	auto lower_bound = transitions.lower_bound ( key );
-	if ( std::find_if ( lower_bound, upper_bound, [ & ] ( const auto & transition ) { return transition.second == to; } ) != upper_bound )
+	auto upper_bound = transitions.upper_bound ( ext::tie ( from, input ) );
+	auto lower_bound = transitions.lower_bound ( ext::tie ( from, input ) );
+	auto iter = std::lower_bound ( lower_bound, upper_bound, to, [ ] ( const auto & transition, const auto & target ) { return transition.second < target; } );
+	if ( iter != upper_bound && to >= iter->second )
 		return false;
 
-	lower_bound = std::lower_bound ( lower_bound, upper_bound, to, [] ( const std::pair < ext::pair < StateType, SymbolType >, StateType > & first, const StateType & second ) { return first.second < second; } );
-
-	transitions.insert ( lower_bound, std::make_pair ( std::move ( key ), std::move ( to ) ) );
+	ext::pair < StateType, SymbolType > key = ext::make_pair ( std::move ( from ), std::move ( input ) );
+	transitions.insert ( iter, std::make_pair ( std::move ( key ), std::move ( to ) ) );
 	return true;
 }
 
 template<class SymbolType, class StateType >
 bool NFA < SymbolType, StateType >::removeTransition ( const StateType & from, const SymbolType & input, const StateType & to ) {
-	auto iter = std::binary_search ( transitions.begin ( ), transitions.end ( ), ext::tie ( from, input, to ), [ & ] ( const std::pair < ext::pair < StateType, SymbolType >, StateType > & transition, const auto & second ) {
-				return ext::tie ( transition.first.first, transition.first.second, transition.second ) < second;
-			} );
-	ext::pair < StateType, SymbolType > key = ext::make_pair ( from, input );
+	auto upper_bound = transitions.upper_bound ( ext::tie ( from, input ) );
+	auto lower_bound = transitions.lower_bound ( ext::tie ( from, input ) );
+	auto iter = std::find_if ( lower_bound, upper_bound, [ & ] ( const auto & transition ) { return transition.second == to; } );
+	if ( iter == upper_bound )
+		return false;
 
-	return transitions[key].erase ( to );
+	transitions.erase ( iter );
+	return true;
 }
 
 template<class SymbolType, class StateType >
diff --git a/alib2data/src/automaton/xml/FSM/EpsilonNFA.h b/alib2data/src/automaton/xml/FSM/EpsilonNFA.h
index 97e7dd4e4c..a4fe1d4c21 100644
--- a/alib2data/src/automaton/xml/FSM/EpsilonNFA.h
+++ b/alib2data/src/automaton/xml/FSM/EpsilonNFA.h
@@ -138,16 +138,15 @@ template < class SymbolType, class EpsilonType, class StateType >
 void xmlApi < automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > >::composeTransitions ( ext::deque < sax::Token > & out, const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & automaton ) {
 	out.emplace_back ( "transitions", sax::Token::TokenType::START_ELEMENT );
 
-	for ( const auto & transition : automaton.getTransitions ( ) )
-		for ( const auto & targetState : transition.second ) {
-			out.emplace_back ( "transition", sax::Token::TokenType::START_ELEMENT );
+	for ( const auto & transition : automaton.getTransitions ( ) ) {
+		out.emplace_back ( "transition", sax::Token::TokenType::START_ELEMENT );
 
-			automaton::AutomatonToXMLComposer::composeTransitionFrom ( out, transition.first.first );
-			automaton::AutomatonToXMLComposer::composeTransitionInputEpsilonSymbol ( out, transition.first.second );
-			automaton::AutomatonToXMLComposer::composeTransitionTo ( out, targetState );
+		automaton::AutomatonToXMLComposer::composeTransitionFrom ( out, transition.first.first );
+		automaton::AutomatonToXMLComposer::composeTransitionInputEpsilonSymbol ( out, transition.first.second );
+		automaton::AutomatonToXMLComposer::composeTransitionTo ( out, transition.second );
 
-			out.emplace_back ( "transition", sax::Token::TokenType::END_ELEMENT );
-		}
+		out.emplace_back ( "transition", sax::Token::TokenType::END_ELEMENT );
+	}
 
 	out.emplace_back ( "transitions", sax::Token::TokenType::END_ELEMENT );
 }
diff --git a/alib2data/test-src/automaton/AutomatonTest.cpp b/alib2data/test-src/automaton/AutomatonTest.cpp
index d7af0b8495..0ed5a75295 100644
--- a/alib2data/test-src/automaton/AutomatonTest.cpp
+++ b/alib2data/test-src/automaton/AutomatonTest.cpp
@@ -92,6 +92,12 @@ SECTION ( "NFA Insert transitions" ) {
 	automaton2.addFinalState ( 3 );
 
 	CHECK ( automaton == automaton2 );
+
+	automaton.removeTransition ( 2, 'b', 3 );
+	automaton2.removeTransition ( 2, 'b', 3 );
+
+	CHECK ( automaton == automaton2 );
+	CHECK ( automaton.getTransitions ( ).size ( ) == 3 );
 }
 
 SECTION ( "SinglePopDPDA Transitions" ) {
diff --git a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h
index 38a70bf568..31f7548068 100644
--- a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h
+++ b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h
@@ -28,7 +28,7 @@ namespace efficient {
 
 class AllEpsilonClosure {
 	template < class StateType >
-	static void process(const ext::map<StateType, ext::set<StateType>>& epsilonTransitions, const StateType * state, ext::map<StateType, ext::set<StateType>>& closures, ext::set<StateType>& visited, ext::set<StateType>& nonvisited);
+	static void process(const ext::multimap<StateType, StateType>& epsilonTransitions, const StateType * state, ext::map<StateType, ext::set<StateType>>& closures, ext::set<StateType>& visited, ext::set<StateType>& nonvisited);
 public:
 	/**
 	 * Computes allEpsilon closure of a state in allEpsilon nonfree automaton
@@ -48,18 +48,19 @@ public:
 };
 
 template < class StateType >
-void AllEpsilonClosure::process(const ext::map<StateType, ext::set<StateType>>& epsilonTransitions, const StateType * state, ext::map<StateType, ext::set<StateType>>& closures, ext::set<StateType>& visited, ext::set<StateType>& nonvisited) {
+void AllEpsilonClosure::process(const ext::multimap<StateType, StateType>& epsilonTransitions, const StateType * state, ext::map<StateType, ext::set<StateType>>& closures, ext::set<StateType>& visited, ext::set<StateType>& nonvisited) {
 	if(visited.count(*state)) return;
 
 	state = &*visited.insert(*state).first;
 	nonvisited.erase(*state);
 
-	auto tos = epsilonTransitions.find(*state);
-	if(tos == epsilonTransitions.end()) return;
+	auto tos = epsilonTransitions.equal_range ( * state );
+	if ( tos.empty ( ) )
+		return;
 
-	for(const StateType& to : tos->second) {
-		process(epsilonTransitions, &to, closures, visited, nonvisited);
-		closures[*state].insert(closures[to].begin(), closures[to].end());
+	for ( const auto & transition : tos ) {
+		process(epsilonTransitions, &transition.second, closures, visited, nonvisited);
+		closures[*state].insert(closures[transition.second].begin(), closures[transition.second].end());
 	}
 }
 
@@ -73,7 +74,7 @@ ext::map<StateType, ext::set<StateType>> AllEpsilonClosure::allEpsilonClosure( c
 	ext::set<StateType> visited;
 	ext::set<StateType> nonvisited = fsm.getStates();
 
-	ext::map<StateType, ext::set<StateType>> epsilonTransitions = fsm.getEpsilonTransitions();
+	ext::multimap<StateType, StateType> epsilonTransitions = fsm.getEpsilonTransitions();
 
 	while(nonvisited.size()) {
 		process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited);
@@ -122,10 +123,11 @@ ext::map<StateType, ext::set<StateType>> AllEpsilonClosure::allEpsilonClosure( c
 	ext::set<StateType> visited;
 	ext::set<StateType> nonvisited = fsm.getStates();
 
-	ext::map<StateType, ext::set<StateType>> epsilonTransitions;
+	ext::multimap<StateType, StateType> epsilonTransitions;
 	for(const std::pair<const ext::pair<StateType, regexp::UnboundedRegExpStructure < SymbolType > >, ext::set<StateType> >& transition : fsm.getTransitions() )
 		if( regexp::properties::RegExpEpsilon::languageContainsEpsilon( transition.first.second ) )
-			epsilonTransitions[transition.first.first].insert(transition.second.begin(), transition.second.end());
+			for ( const auto & to : transition.second )
+				epsilonTransitions.insert ( transition.first.first, to );
 
 	while(nonvisited.size()) {
 		process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited);
@@ -150,10 +152,11 @@ ext::map<StateType, ext::set<StateType>> AllEpsilonClosure::allEpsilonClosure( c
 	ext::set<StateType> visited;
 	ext::set<StateType> nonvisited = fsm.getStates();
 
-	ext::map<StateType, ext::set<StateType>> epsilonTransitions;
+	ext::multimap<StateType, StateType > epsilonTransitions;
 	for(const std::pair<const ext::pair<StateType, ext::vector < SymbolType > >, ext::set<StateType> >& transition : fsm.getTransitions() )
 		if( transition.first.second.size() == 0 )
-			epsilonTransitions[transition.first.first].insert(transition.second.begin(), transition.second.end());
+			for ( const auto & to : transition.second )
+				epsilonTransitions.insert ( transition.first.first, to );
 
 	while(nonvisited.size()) {
 		process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited);
diff --git a/alib2elgo/src/automaton/properties/efficient/ReachableStates.h b/alib2elgo/src/automaton/properties/efficient/ReachableStates.h
index a47673c8f3..880ffd63fe 100644
--- a/alib2elgo/src/automaton/properties/efficient/ReachableStates.h
+++ b/alib2elgo/src/automaton/properties/efficient/ReachableStates.h
@@ -33,6 +33,8 @@ public:
 	 */
 	template < class T >
 	static ext::set < typename automaton::StateTypeOfAutomaton < T > > reachableStates( const T & fsm );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static ext::set<StateType> reachableStates( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm );
 	template < class SymbolType, class StateType >
 	static ext::set<StateType> reachableStates( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm );
 	template < class SymbolType, class StateType >
@@ -87,6 +89,28 @@ ext::set<StateType> ReachableStates::reachableStates( const automaton::MultiInit
 	return visited;
 }
 
+template < class SymbolType, class EpsilonType, class StateType >
+ext::set<StateType> ReachableStates::reachableStates( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm ) {
+	ext::map<StateType, ext::set<StateType>> transitions;
+	for(const auto& transition : fsm.getTransitions())
+		transitions[transition.first.first].insert(transition.second);
+
+	ext::deque<StateType> queue { fsm.getInitialState( ) };
+	ext::set<StateType> visited { fsm.getInitialState( ) };
+
+	while( !queue.empty() ) {
+		const ext::set<StateType>& to = transitions[queue.front()];
+		queue.pop_front();
+
+		for(const StateType& process : to)
+			if(visited.insert(process).second) {
+				queue.push_back(std::move(const_cast<StateType&>(process)));
+			}
+	}
+
+	return visited;
+}
+
 template < class SymbolType, class StateType >
 ext::set<StateType> ReachableStates::reachableStates( const automaton::NFA < SymbolType, StateType > & fsm ) {
 	ext::map<StateType, ext::set<StateType>> transitions;
diff --git a/alib2elgo/src/automaton/properties/efficient/UsefulStates.h b/alib2elgo/src/automaton/properties/efficient/UsefulStates.h
index ee8485d79a..73507583b8 100644
--- a/alib2elgo/src/automaton/properties/efficient/UsefulStates.h
+++ b/alib2elgo/src/automaton/properties/efficient/UsefulStates.h
@@ -33,6 +33,8 @@ public:
 	 */
 	template < class T >
 	static ext::set < typename automaton::StateTypeOfAutomaton < T > > usefulStates( const T & fsm );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static ext::set<StateType> usefulStates( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm );
 	template < class SymbolType, class StateType >
 	static ext::set<StateType> usefulStates( const automaton::NFA < SymbolType, StateType > & fsm );
 	template < class SymbolType, class StateType >
@@ -64,6 +66,28 @@ ext::set < typename automaton::StateTypeOfAutomaton < T > > UsefulStates::useful
 	return visited;
 }
 
+template < class SymbolType, class EpsilonType, class StateType >
+ext::set<StateType> UsefulStates::usefulStates( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm ) {
+	ext::map<StateType, ext::set<StateType>> reversedTransitions;
+	for(const auto& transition : fsm.getTransitions())
+		reversedTransitions[transition.second].insert(transition.first.first);
+
+	ext::deque<StateType> queue ( fsm.getFinalStates( ).begin(), fsm.getFinalStates().end() );
+	ext::set<StateType> visited = fsm.getFinalStates( );
+
+	while( !queue.empty() ) {
+		const ext::set<StateType>& to = reversedTransitions[queue.front()];
+		queue.pop_front();
+
+		for(const StateType& process : to)
+			if(visited.insert(process).second) {
+				queue.push_back(std::move(const_cast<StateType&>(process)));
+			}
+	}
+
+	return visited;
+}
+
 template < class SymbolType, class StateType >
 ext::set<StateType> UsefulStates::usefulStates( const automaton::NFA < SymbolType, StateType > & fsm ) {
 	ext::map<StateType, ext::set<StateType>> reversedTransitions;
diff --git a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.h b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.h
index 58bbb093e7..70c05189ab 100644
--- a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.h
+++ b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverIncoming.h
@@ -63,7 +63,7 @@ automaton::NFA < SymbolType, StateType > EpsilonRemoverIncoming::remove ( const
 
 	ext::map < StateType, ext::set < StateType > > closures = automaton::properties::efficient::AllEpsilonClosure::allEpsilonClosure ( origFSM );
 
-	ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > origTransitions = origFSM.getSymbolTransitions ( );
+	ext::multimap < ext::pair < StateType, SymbolType >, StateType > origTransitions = origFSM.getSymbolTransitions ( );
 
 	/**
 	 * Step 1 from Melichar 2.41
@@ -71,11 +71,11 @@ automaton::NFA < SymbolType, StateType > EpsilonRemoverIncoming::remove ( const
 	for ( const auto & from : origFSM.getStates ( ) )
 		for ( const auto & fromClosure : closures [ from ] )
 			for ( const auto & symbol : origFSM.getInputAlphabet ( ) ) {
-				auto transitions = origTransitions.find ( ext::make_pair ( fromClosure, symbol ) );
-				if ( transitions == origTransitions.end ( ) ) continue;
+				auto transitions = origTransitions.equal_range ( ext::make_pair ( fromClosure, symbol ) );
+				if ( transitions.empty ( ) ) continue;
 
-				for ( const auto & to : transitions->second )
-					fsm.addTransition( from, symbol, to );
+				for ( const auto & transition : transitions )
+					fsm.addTransition( from, symbol, transition.second );
 			}
 
 	/**
diff --git a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.h b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.h
index 28a48477b4..5c77448301 100644
--- a/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.h
+++ b/alib2elgo/src/automaton/simplify/efficient/EpsilonRemoverOutgoing.h
@@ -63,12 +63,11 @@ automaton::MultiInitialStateNFA < SymbolType, StateType > EpsilonRemoverOutgoing
 
 	ext::map < StateType, ext::set < StateType > > closures = automaton::properties::efficient::AllEpsilonClosure::allEpsilonClosure ( origFSM );
 
-	ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > transitions = origFSM.getSymbolTransitions ( );
+	ext::multimap < ext::pair < StateType, SymbolType >, StateType > transitions = origFSM.getSymbolTransitions ( );
 
-	for ( const std::pair < const ext::pair < StateType, SymbolType >, ext::set < StateType > > & transition : transitions )
-		for ( const StateType & to : transition.second )
-			for ( const StateType & toClosure : closures [ to ] )
-				fsm.addTransition ( transition.first.first, transition.first.second, toClosure );
+	for ( const std::pair < const ext::pair < StateType, SymbolType >, StateType > & transition : transitions )
+		for ( const StateType & toClosure : closures [ transition.second ] )
+			fsm.addTransition ( transition.first.first, transition.first.second, toClosure );
 
 	/**
 	 * Step 2 from Melichar 2.41
diff --git a/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h b/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h
index 26d75958b5..6c30a67bb3 100644
--- a/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h
+++ b/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h
@@ -34,6 +34,8 @@ public:
 	 */
 	template < class T >
 	static T remove( const T & automaton );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > remove( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm );
 	template < class SymbolType, class StateType >
 	static automaton::NFA < SymbolType, StateType > remove( const automaton::NFA < SymbolType, StateType > & fsm );
 	template < class SymbolType, class StateType >
@@ -71,6 +73,32 @@ T UnreachableStatesRemover::remove ( const T & fsm ) {
 	return M;
 }
 
+template < class SymbolType, class EpsilonType, class StateType >
+automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > UnreachableStatesRemover::remove( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm ) {
+	// 1a
+	ext::set<StateType> Qa = automaton::properties::efficient::ReachableStates::reachableStates( fsm );
+
+	// 2
+	automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > 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 );
+
+	ext::set<StateType> 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 < class SymbolType, class StateType >
 automaton::NFA < SymbolType, StateType > UnreachableStatesRemover::remove( const automaton::NFA < SymbolType, StateType > & fsm ) {
 	// 1a
diff --git a/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h b/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h
index 7790915854..88ba699037 100644
--- a/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h
+++ b/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h
@@ -34,6 +34,8 @@ public:
 	 */
 	template < class T >
 	static T remove( const T & automaton );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > remove( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm );
 	template < class SymbolType, class StateType >
 	static automaton::NFA < SymbolType, StateType > remove( const automaton::NFA < SymbolType, StateType > & fsm );
 	template < class SymbolType, class StateType >
@@ -73,6 +75,34 @@ T UselessStatesRemover::remove( const T & fsm ) {
 	return M;
 }
 
+template < class SymbolType, class EpsilonType, class StateType >
+automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > UselessStatesRemover::remove( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm ) {
+	// 1.
+	ext::set<StateType> Qu = automaton::properties::efficient::UsefulStates::usefulStates( fsm );
+
+	// 2.
+	automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > 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 < class SymbolType, class StateType >
 automaton::NFA < SymbolType, StateType > UselessStatesRemover::remove( const automaton::NFA < SymbolType, StateType > & fsm ) {
 	// 1.
diff --git a/alib2str/src/automaton/string/FSM/EpsilonNFA.h b/alib2str/src/automaton/string/FSM/EpsilonNFA.h
index 494c431e44..1aca4d6b9d 100644
--- a/alib2str/src/automaton/string/FSM/EpsilonNFA.h
+++ b/alib2str/src/automaton/string/FSM/EpsilonNFA.h
@@ -171,33 +171,33 @@ void stringApi < automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > >:
 
 template < class SymbolType, class EpsilonType, class StateType >
 void stringApi < automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > >::composeTransitionsFromState(std::ostream& output, const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & automaton, const StateType & from) {
-	ext::map<ext::pair<StateType, SymbolType>, ext::set<StateType> > symbolTransitionsFromState = automaton.getSymbolTransitionsFromState(from);
-
+	ext::multimap<ext::pair<StateType, SymbolType>, StateType > symbolTransitionsFromState = automaton.getSymbolTransitionsFromState(from);
 	for(const SymbolType& inputSymbol : automaton.getInputAlphabet()) {
-		const typename ext::map<ext::pair<StateType, SymbolType>, ext::set<StateType> >::iterator toStates = symbolTransitionsFromState.find(ext::make_pair(from, inputSymbol));
-		if(toStates == symbolTransitionsFromState.end() || toStates->second.size() == 0) {
+		const auto toStates = symbolTransitionsFromState.equal_range(ext::make_pair(from, inputSymbol));
+		if ( toStates.empty ( ) ) {
 			output << " -";
 		} else {
 			bool sign = false;
-			for(const StateType& to : toStates->second) {
+			for(const auto & transition : toStates ) {
 				output << (sign ? "|" : " ");
-				core::stringApi < StateType >::compose ( output, to );
+				core::stringApi<StateType>::compose(output, transition.second);
 				sign = true;
 			}
 		}
 	}
 
-	ext::map<StateType, ext::set<StateType> > epsilonTransitionsFromState = automaton.getEpsilonTransitionsFromState(from);
-	if(epsilonTransitionsFromState.size() == 0 || epsilonTransitionsFromState.begin()->second.size() == 0) {
+	ext::multimap<StateType, StateType > epsilonTransitionsFromState = automaton.getEpsilonTransitionsFromState(from);
+	if ( epsilonTransitionsFromState.empty ( ) ) {
 		output << " -";
 	} else {
 		bool sign = false;
-		for(const StateType& to : epsilonTransitionsFromState.begin()->second) {
+		for(const auto & transition : epsilonTransitionsFromState ) {
 			output << (sign ? "|" : " ");
-			core::stringApi < StateType >::compose ( output, to );
+			core::stringApi<StateType>::compose(output, transition.second);
 			sign = true;
 		}
 	}
+
 }
 
 } /* namespace core */
-- 
GitLab