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