From 81afeebd2d1ccca5399d7923d50df1f8fa08c10e Mon Sep 17 00:00:00 2001
From: Jan Travnicek <jan.travnicek@.fit.cvut.cz>
Date: Tue, 2 Apr 2019 11:05:51 +0200
Subject: [PATCH] use multimap in multi initial state epsilon nfa

---
 .../src/automaton/convert/ToRegExpKleene.h    |   2 +-
 .../automaton/simplify/SingleInitialState.h   |   6 +-
 .../SingleInitialStateEpsilonTransition.h     |   3 +-
 alib2data/src/automaton/FSM/CompactNFA.h      |  12 +-
 alib2data/src/automaton/FSM/ExtendedNFA.h     |   6 +-
 .../FSM/MultiInitialStateEpsilonNFA.h         | 206 ++++++------------
 .../src/automaton/FSM/MultiInitialStateNFA.h  |  13 +-
 alib2data/src/automaton/FSM/NFA.h             |   3 +-
 .../xml/FSM/MultiInitialStateEpsilonNFA.h     |  15 +-
 9 files changed, 96 insertions(+), 170 deletions(-)

diff --git a/alib2algo/src/automaton/convert/ToRegExpKleene.h b/alib2algo/src/automaton/convert/ToRegExpKleene.h
index 87a9ac15e6..f15c664d53 100644
--- a/alib2algo/src/automaton/convert/ToRegExpKleene.h
+++ b/alib2algo/src/automaton/convert/ToRegExpKleene.h
@@ -184,7 +184,7 @@ const regexp::UnboundedRegExpStructure < SymbolType > ToRegExpKleene::transition
 		ret.setStructure ( regexp::UnboundedRegExpEpsilon < SymbolType > ( ) );
 
 	for ( const auto & transition: automaton.getTransitionsFromState ( from ) ) {
-		if ( transition.second.count ( to ) ) {
+		if ( transition.second == to ) {
 			if ( transition.first.second.template is < SymbolType > ( ) )
 				ret = regexp::RegExpAlternate::alternate ( ret, regexp::UnboundedRegExpStructure < SymbolType > ( regexp::UnboundedRegExpSymbol < SymbolType > ( transition.first.second.template get < SymbolType > ( ) ) ) );
 			else
diff --git a/alib2algo/src/automaton/simplify/SingleInitialState.h b/alib2algo/src/automaton/simplify/SingleInitialState.h
index dc19c2c7d7..61c6b37e1d 100644
--- a/alib2algo/src/automaton/simplify/SingleInitialState.h
+++ b/alib2algo/src/automaton/simplify/SingleInitialState.h
@@ -142,12 +142,10 @@ automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > SingleInitialState:
 	// step 2
 	for ( const auto & q : automaton.getInitialStates ( ) )
 		for(const auto & kv : automaton.getTransitionsFromState ( q ) )
-			for ( const StateType & to : kv.second )
-				res.addTransition ( q0, kv.first.second, to );
+			res.addTransition ( q0, kv.first.second, kv.second );
 
 	for ( const auto & t : automaton.getTransitions ( ) )
-		for ( const StateType & q : t.second )
-			res.addTransition ( t.first.first, t.first.second, q );
+		res.addTransition ( t.first.first, t.first.second, t.second );
 
 	// step 4, 5
 	ext::set < StateType > intersection;
diff --git a/alib2algo/src/automaton/simplify/SingleInitialStateEpsilonTransition.h b/alib2algo/src/automaton/simplify/SingleInitialStateEpsilonTransition.h
index 15cf65b915..7b1cea9309 100644
--- a/alib2algo/src/automaton/simplify/SingleInitialStateEpsilonTransition.h
+++ b/alib2algo/src/automaton/simplify/SingleInitialStateEpsilonTransition.h
@@ -134,8 +134,7 @@ automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > SingleInitialStateE
 		res.addTransition ( q0, q );
 
 	for ( const auto & t : automaton.getTransitions ( ) )
-		for ( const StateType & q : t.second )
-			res.addTransition ( t.first.first, t.first.second, q );
+		res.addTransition ( t.first.first, t.first.second, t.second );
 
 	// step 4, 5
 	res.setFinalStates ( automaton.getFinalStates ( ) );
diff --git a/alib2data/src/automaton/FSM/CompactNFA.h b/alib2data/src/automaton/FSM/CompactNFA.h
index 62fff57b1e..504513af1e 100644
--- a/alib2data/src/automaton/FSM/CompactNFA.h
+++ b/alib2data/src/automaton/FSM/CompactNFA.h
@@ -441,11 +441,10 @@ template < class SymbolType, class StateType >
 template < class EpsilonType >
 CompactNFA < SymbolType, StateType >::CompactNFA ( const MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & other ) : CompactNFA ( 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 ( ) )
-		for ( const auto & to : transition.second )
-			if ( transition.first.second.template is < EpsilonType > ( ) )
-				transitions.insert ( ext::make_pair ( transition.first.first, ext::vector < SymbolType > { } ), to );
-			else
-				transitions.insert ( ext::make_pair ( transition.first.first, ext::vector < SymbolType > { transition.first.second.template get < SymbolType > ( ) } ), to );
+		if ( transition.first.second.template is < EpsilonType > ( ) )
+			transitions.insert ( ext::make_pair ( transition.first.first, ext::vector < SymbolType > { } ), transition.second );
+		else
+			transitions.insert ( ext::make_pair ( transition.first.first, ext::vector < SymbolType > { transition.first.second.template get < SymbolType > ( ) } ), transition.second );
 
 	for ( const auto & state : other.getInitialStates ( ) )
 		transitions.insert ( ext::make_pair ( this->getInitialState ( ), ext::vector < SymbolType > { } ), state );
@@ -478,8 +477,7 @@ CompactNFA < SymbolType, StateType >::CompactNFA ( const NFA < SymbolType, State
 
 template < class SymbolType, class StateType >
 CompactNFA < SymbolType, StateType >::CompactNFA ( const CompactDFA < SymbolType, StateType > & other ) : CompactNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
-	for ( const auto & transition : other.getTransitions ( ) )
-		transitions.insert ( transition );
+	transitions.insert ( other.getTransitions ( ).begin ( ), other.getTransitions ( ).end ( ) );
 }
 
 template < class SymbolType, class StateType >
diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.h b/alib2data/src/automaton/FSM/ExtendedNFA.h
index 96256abb06..5cd619ad25 100644
--- a/alib2data/src/automaton/FSM/ExtendedNFA.h
+++ b/alib2data/src/automaton/FSM/ExtendedNFA.h
@@ -457,12 +457,10 @@ ExtendedNFA < SymbolType, StateType >::ExtendedNFA ( const MultiInitialStateEpsi
 	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 > ( ) ) );
-			for ( const StateType & to : transition.second )
-				transitions.insert ( key, to );
+			transitions.insert ( key, 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 > ( ) ) ) );
-			for ( const StateType & to : transition.second )
-				transitions.insert ( key, to );
+			transitions.insert ( key, transition.second );
 		}
 	}
 
diff --git a/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h b/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h
index 915871184c..e58d115392 100644
--- a/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h
+++ b/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h
@@ -27,7 +27,7 @@
 #include <ostream>
 #include <sstream>
 
-#include <alib/map>
+#include <alib/multimap>
 #include <alib/set>
 #include <alib/variant>
 #include <alib/compare>
@@ -81,7 +81,7 @@ class MultiInitialStateEpsilonNFA final : public ext::CompareOperators < MultiIn
 	/**
 	 * 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:
 	/**
@@ -387,44 +387,6 @@ public:
 	 */
 	bool addTransition ( StateType from, 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 \cup \{\epsilon\}, P(Q) is a powerset of states.
-	 *
-	 * \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 current the source state (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::set < StateType > to );
-
 	/**
 	 * \brief Removes a transition from the automaton.
 	 *
@@ -455,28 +417,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.
@@ -485,7 +447,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.
@@ -494,7 +456,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.
@@ -503,7 +465,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.
@@ -512,7 +474,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.
@@ -521,7 +483,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.
@@ -530,7 +492,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.
@@ -606,17 +568,14 @@ MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::MultiInitial
 
 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].insert ( transition.second );
-	}
+	transitions = other.getTransitions ( );
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
 MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::MultiInitialStateEpsilonNFA ( const MultiInitialStateNFA < SymbolType, StateType > & other ) : MultiInitialStateEpsilonNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialStates ( ), 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].insert ( transition.second );
+		transitions.insert ( key, transition.second );
 	}
 }
 
@@ -624,7 +583,7 @@ template<class SymbolType, class EpsilonType, class StateType >
 MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::MultiInitialStateEpsilonNFA ( const NFA < SymbolType, 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].insert ( transition.second );
+		transitions.insert ( key, transition.second );
 	}
 }
 
@@ -632,7 +591,7 @@ template<class SymbolType, class EpsilonType, class StateType >
 MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::MultiInitialStateEpsilonNFA ( const DFA < SymbolType, 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].insert ( transition.second );
+		transitions.insert( key, transition.second );
 	}
 }
 
@@ -641,15 +600,21 @@ bool MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::addTran
 	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 >
@@ -666,36 +631,6 @@ bool MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::addTran
 	return addTransition ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) );
 }
 
-template < class SymbolType, class EpsilonType, class StateType >
-void MultiInitialStateEpsilonNFA < 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 MultiInitialStateEpsilonNFA < 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 MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::addTransitions ( StateType from, ext::set < StateType > to ) {
-	auto inputVariant = ext::variant < EpsilonType, SymbolType >::template from < EpsilonType > ( );
-
-	addTransitions ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) );
-}
-
 template<class SymbolType, class EpsilonType, class StateType >
 bool MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::removeTransition ( const StateType & from, const SymbolType & input, const StateType & to ) {
 	ext::variant < EpsilonType, SymbolType > inputVariant ( input );
@@ -714,125 +649,124 @@ bool MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::removeT
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
-const ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitions ( ) const & {
+const ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > & MultiInitialStateEpsilonNFA < 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 > > && MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitions ( ) && {
+ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > && MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitions ( ) && {
 	return std::move ( transitions );
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
-ext::map < StateType, ext::set < StateType > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitions ( ) const {
-	ext::map < StateType, ext::set < StateType > > result;
+ext::multimap < StateType, StateType > MultiInitialStateEpsilonNFA < 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 > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitions ( ) const {
-	ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > result;
+ext::multimap < ext::pair < StateType, SymbolType >, StateType > MultiInitialStateEpsilonNFA < 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 > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitionsFromState ( const StateType & from ) const {
+ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > MultiInitialStateEpsilonNFA < 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 > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitionsFromState ( const StateType & from ) const {
+ext::multimap < StateType, StateType > MultiInitialStateEpsilonNFA < 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 );
+	ext::multimap < StateType, StateType > res;
 
-	if ( transition != transitions.end ( ) )
-		res.insert ( from, transition->second );
+	for ( const auto & 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 > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitionsFromState ( const StateType & from ) const {
+ext::multimap < ext::pair < StateType, SymbolType >, StateType > MultiInitialStateEpsilonNFA < 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 ( 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 > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitionsToState ( const StateType & to ) const {
+ext::multimap < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, StateType > MultiInitialStateEpsilonNFA < 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.first, to );
 
 	return transitionsToState;
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
-ext::map < StateType, ext::set < StateType > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitionsToState ( const StateType & to ) const {
+ext::multimap < StateType, StateType > MultiInitialStateEpsilonNFA < 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 > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitionsToState ( const StateType & to ) const {
+ext::multimap < ext::pair < StateType, SymbolType >, StateType > MultiInitialStateEpsilonNFA < 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::make_pair ( transition.first.first, transition.first.second.template get < SymbolType > ( ) ), to );
 
 	return transitionsToState;
 }
 
 template<class SymbolType, class EpsilonType, class StateType >
 bool MultiInitialStateEpsilonNFA < 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;
 
@@ -841,7 +775,7 @@ bool MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::isEpsil
 
 template<class SymbolType, class EpsilonType, class StateType >
 bool MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::isDeterministic ( ) 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.second.size ( ) > 1 )
 			return false;
 
@@ -893,7 +827,7 @@ public:
 	 * \returns true if the symbol is used, false othervise
 	 */
 	static bool used ( const automaton::MultiInitialStateEpsilonNFA < 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;
 
@@ -947,8 +881,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;
@@ -1079,12 +1013,12 @@ struct normalize < automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonT
 
 		automaton::MultiInitialStateEpsilonNFA < > res ( std::move ( states ), std::move ( alphabet ), std::move ( initialStates ), 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::normalizeStates ( 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/MultiInitialStateNFA.h b/alib2data/src/automaton/FSM/MultiInitialStateNFA.h
index b221c01923..9025e396c2 100644
--- a/alib2data/src/automaton/FSM/MultiInitialStateNFA.h
+++ b/alib2data/src/automaton/FSM/MultiInitialStateNFA.h
@@ -446,14 +446,12 @@ MultiInitialStateNFA < SymbolType, StateType >::MultiInitialStateNFA ( ) : Multi
 
 template < class SymbolType, class StateType >
 MultiInitialStateNFA < SymbolType, StateType >::MultiInitialStateNFA ( const DFA < SymbolType, StateType > & other ) : MultiInitialStateNFA ( other.getStates ( ), other.getInputAlphabet ( ), { other.getInitialState ( ) }, other.getFinalStates ( ) ) {
-	for ( const auto & transition : other.getTransitions ( ) )
-		transitions.insert ( transition );
+	transitions.insert ( other.getTransitions ( ).begin ( ), other.getTransitions ( ).end ( ) );
 }
 
 template < class SymbolType, class StateType >
 MultiInitialStateNFA < SymbolType, StateType >::MultiInitialStateNFA ( const NFA < SymbolType, StateType > & other ) : MultiInitialStateNFA ( other.getStates ( ), other.getInputAlphabet ( ), { other.getInitialState ( ) }, other.getFinalStates ( ) ) {
-	for ( const auto & transition : other.getTransitions ( ) )
-		transitions.insert ( transition );
+	transitions = other.getTransitions ( );
 }
 
 template < class SymbolType, class StateType >
@@ -530,8 +528,11 @@ ext::multimap < ext::pair < StateType, SymbolType >, StateType > MultiInitialSta
 
 template < class SymbolType, class StateType >
 bool MultiInitialStateNFA < SymbolType, StateType >::isDeterministic ( ) const {
-	for ( const std::pair < const ext::pair < StateType, 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 getInitialStates ( ).size ( ) == 1;
diff --git a/alib2data/src/automaton/FSM/NFA.h b/alib2data/src/automaton/FSM/NFA.h
index f26025c801..769050483b 100644
--- a/alib2data/src/automaton/FSM/NFA.h
+++ b/alib2data/src/automaton/FSM/NFA.h
@@ -407,8 +407,7 @@ NFA < SymbolType, StateType >::NFA ( StateType initialState ) : NFA ( ext::set <
 
 template<class SymbolType, class StateType >
 NFA < SymbolType, StateType >::NFA ( const DFA < SymbolType, StateType > & other ) : NFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) {
-	for ( const auto & transition : other.getTransitions ( ) )
-		transitions.insert ( transition );
+	transitions.insert ( other.getTransitions ( ).begin ( ), other.getTransitions ( ).end ( ) );
 }
 
 template<class SymbolType, class StateType >
diff --git a/alib2data/src/automaton/xml/FSM/MultiInitialStateEpsilonNFA.h b/alib2data/src/automaton/xml/FSM/MultiInitialStateEpsilonNFA.h
index 2423f14cd1..270163bad6 100644
--- a/alib2data/src/automaton/xml/FSM/MultiInitialStateEpsilonNFA.h
+++ b/alib2data/src/automaton/xml/FSM/MultiInitialStateEpsilonNFA.h
@@ -139,16 +139,15 @@ template < class SymbolType, class EpsilonType, class StateType >
 void xmlApi < automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > >::composeTransitions ( ext::deque < sax::Token > & out, const automaton::MultiInitialStateEpsilonNFA < 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 );
 }
-- 
GitLab