diff --git a/alib2algo/src/automaton/properties/AllEpsilonClosure.h b/alib2algo/src/automaton/properties/AllEpsilonClosure.h index 9e38dc19184f1218d5d62b25e66f9b28331e5221..c85ee818846c41c09c2be79a5f9408ad3c7e4e96 100644 --- a/alib2algo/src/automaton/properties/AllEpsilonClosure.h +++ b/alib2algo/src/automaton/properties/AllEpsilonClosure.h @@ -209,9 +209,9 @@ ext::map<StateType, ext::set<StateType>> AllEpsilonClosure::allEpsilonClosure( c ext::map<StateType, ext::set<StateType>> res; ext::map<StateType, ext::set<StateType>> step; - for(const std::pair<const std::pair<StateType, ext::vector < SymbolType > >, ext::set<StateType> >& transition : fsm.getTransitions() ) + for(const std::pair<const std::pair<StateType, ext::vector < SymbolType > >, StateType >& transition : fsm.getTransitions() ) if( transition.first.second.size() == 0 ) - step[transition.first.first].insert(transition.second.begin(), transition.second.end()); + step[transition.first.first].insert(transition.second); for(const StateType& state : fsm.getStates()) step[state].insert(state); diff --git a/alib2algo/src/automaton/properties/EpsilonClosure.h b/alib2algo/src/automaton/properties/EpsilonClosure.h index f9a22f4f8ff2a9a579bb13ca00b9c8141402ea9a..6fa66d49254f3f47093b589411be7d23d82ca522 100644 --- a/alib2algo/src/automaton/properties/EpsilonClosure.h +++ b/alib2algo/src/automaton/properties/EpsilonClosure.h @@ -237,9 +237,8 @@ ext::set<StateType> EpsilonClosure::epsilonClosure( const automaton::CompactNFA for( const auto & transition : fsm.getTransitionsFromState( p ) ) if( transition.first.second.size() == 0 ) - for (const auto & to : transition.second ) - if( visited [ to ] == false ) - queue.push( to ); + if( visited [ transition.second ] == false ) + queue.push( transition.second ); } return closure; diff --git a/alib2algo/src/automaton/properties/InfiniteLanguage.h b/alib2algo/src/automaton/properties/InfiniteLanguage.h index 00c11e6da67018fbfd3205170de15edbb14b1cc1..21372c4b85e7700f9ad65ac6ec9e16ba2087e4ae 100644 --- a/alib2algo/src/automaton/properties/InfiniteLanguage.h +++ b/alib2algo/src/automaton/properties/InfiniteLanguage.h @@ -74,14 +74,12 @@ bool InfiniteLanguage::infinite ( const automaton::NFA < SymbolType, StateType > q.pop ( ); for ( const auto transition : fsm.getTransitionsFromState ( state ) ) { - for ( const StateType & target : transition.second ) { - auto it = visited.find ( target ); - if ( it != visited.end ( ) && usefulStates.count ( target ) ) { - return true; - } else if ( it == visited.end ( ) ) { - visited.insert ( target ); - q.push ( target ); - } + auto it = visited.find ( transition.second ); + if ( it != visited.end ( ) && usefulStates.count ( transition.second ) ) { + return true; + } else if ( it == visited.end ( ) ) { + visited.insert ( transition.second ); + q.push ( transition.second ); } } } diff --git a/alib2algo/src/automaton/properties/ReachableStates.h b/alib2algo/src/automaton/properties/ReachableStates.h index 1e4b7e9d27a2eac571748ba0334fcdc1f12c16d1..b68c7c5bbf9d4bd3fb12fcc85a796095111fc875 100644 --- a/alib2algo/src/automaton/properties/ReachableStates.h +++ b/alib2algo/src/automaton/properties/ReachableStates.h @@ -74,34 +74,6 @@ 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 StateType > - static ext::set<StateType> reachableStates( const automaton::CompactNFA < SymbolType, StateType > & fsm ); - - /** - * Finds all reachable states of a deterministic 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 deterministic finite automaton - * @return set of reachable states from the initial state of @p fsm - */ - template < class SymbolType, class StateType > - static ext::set<StateType> reachableStates( const automaton::ExtendedNFA < SymbolType, StateType > & fsm ); - /** * Finds all reachable states of a deterministic tree automaton. * Using closure implementation of the BFS algorithm. @@ -185,58 +157,6 @@ ext::set<StateType> ReachableStates::reachableStates( const automaton::MultiInit return Qi.at( i ); } -template < class SymbolType, class StateType > -ext::set<StateType> ReachableStates::reachableStates( const automaton::CompactNFA < SymbolType, 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.begin(), transition.second.end() ); - - 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::ExtendedNFA < SymbolType, 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 RankType, class StateType > ext::set<StateType> ReachableStates::reachableStates( const automaton::DFTA < SymbolType, RankType, StateType > & fta ) { // 1a diff --git a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h index c4c9957f80b7c7ce63f2eba357c7311354d4f74b..9a6aebb648bd0f052ee51c776811ad87d8b2b875 100644 --- a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h +++ b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h @@ -63,22 +63,6 @@ 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 StateType > - static automaton::ExtendedNFA < SymbolType, StateType > remove( const automaton::ExtendedNFA < SymbolType, StateType > & fsm ); - - /** - * @overload - * @tparam SymbolType Type for input symbols. - * @tparam StateType Type for states. - */ - template < class SymbolType, class StateType > - static automaton::CompactNFA < SymbolType, StateType > remove( const automaton::CompactNFA < SymbolType, StateType > & fsm ); - /** * @overload * @tparam SymbolType Type for input symbols. @@ -148,59 +132,6 @@ T UnreachableStatesRemover::remove ( const T & fsm ) { return M; } -template < class SymbolType, class StateType > -automaton::ExtendedNFA < SymbolType, StateType > UnreachableStatesRemover::remove( const automaton::ExtendedNFA < SymbolType, StateType > & fsm ) { - // 1a - ext::set<StateType> Qa = automaton::properties::ReachableStates::reachableStates( fsm ); - - // 2 - automaton::ExtendedNFA < SymbolType, 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::CompactNFA < SymbolType, StateType > UnreachableStatesRemover::remove( const automaton::CompactNFA < SymbolType, StateType > & fsm ) { - // 1a - ext::set<StateType> Qa = automaton::properties::ReachableStates::reachableStates( fsm ); - - // 2 - automaton::CompactNFA < SymbolType, 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 ) ) - for(const auto& to : transition.second ) - M.addTransition( transition.first.first, transition.first.second, to ); - - 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::MultiInitialStateNFA < SymbolType, StateType > UnreachableStatesRemover::remove( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm ) { // 1a diff --git a/alib2algo/src/automaton/simplify/UselessStatesRemover.h b/alib2algo/src/automaton/simplify/UselessStatesRemover.h index 17180af7d850db23432f21086ce4d1d4efb73eb0..b7fc891871ea600ed5f7f926f39b73f8f0944535 100644 --- a/alib2algo/src/automaton/simplify/UselessStatesRemover.h +++ b/alib2algo/src/automaton/simplify/UselessStatesRemover.h @@ -59,22 +59,6 @@ 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 StateType > - static automaton::ExtendedNFA < SymbolType, StateType > remove( const automaton::ExtendedNFA < SymbolType, StateType > & fsm ); - - /** - * @overload - * @tparam SymbolType Type for input symbols. - * @tparam StateType Type for states. - */ - template < class SymbolType, class StateType > - static automaton::CompactNFA < SymbolType, StateType > remove( const automaton::CompactNFA < SymbolType, StateType > & fsm ); - /** * @overload * @tparam SymbolType Type for input symbols. @@ -140,63 +124,6 @@ T UselessStatesRemover::remove( const T & fsm ) { return M; } -template < class SymbolType, class StateType > -automaton::ExtendedNFA < SymbolType, StateType > UselessStatesRemover::remove( const automaton::ExtendedNFA < SymbolType, StateType > & fsm ) { - // 1. - ext::set<StateType> Qu = automaton::properties::UsefulStates::usefulStates( fsm ); - - // 2. - automaton::ExtendedNFA < SymbolType, 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::CompactNFA < SymbolType, StateType > UselessStatesRemover::remove( const automaton::CompactNFA < SymbolType, StateType > & fsm ) { - // 1. - ext::set<StateType> Qu = automaton::properties::UsefulStates::usefulStates( fsm ); - - // 2. - automaton::CompactNFA < SymbolType, 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( ) ) - for( const auto & to : t.second ) - if( /* this part is not needed Qu.count(t.first.first) ) && */ Qu.count(to) ) - M.addTransition( t.first.first, t.first.second, to ); - - for( const auto & q : fsm.getFinalStates( ) ) - M.addFinalState( q ); - - return M; -} - template < class SymbolType, class StateType > automaton::MultiInitialStateNFA < SymbolType, StateType > UselessStatesRemover::remove( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm ) { // 1. diff --git a/alib2aux/src/convert/DotConverter.h b/alib2aux/src/convert/DotConverter.h index 23419be3bec3a51c8e0ea8d3254996f7058d3983..faaed8bde46095adb8fb60244c5e2859774eb746 100644 --- a/alib2aux/src/convert/DotConverter.h +++ b/alib2aux/src/convert/DotConverter.h @@ -954,22 +954,20 @@ void DotConverter::transitions(const automaton::CompactNFA < SymbolType, StateTy for (const auto& transition : fsm.getTransitions()) { std::string symbol = replace ( factory::StringDataFactory::toString ( string::stringFrom ( transition.first.second ) ), "\"", "\\\"" ); - 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 26863a053fc90c72c1fbfc0a4fde7c9620ba1dd5..7a611ba4b5c5c93226cb61e9b86aa53a90aa9cf8 100644 --- a/alib2aux/src/convert/GasTexConverter.h +++ b/alib2aux/src/convert/GasTexConverter.h @@ -982,17 +982,15 @@ void GasTexConverter::transitions(const automaton::CompactNFA < SymbolType, Stat 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 = replace ( factory::StringDataFactory::toString ( string::stringFrom(transition.first.second )), "\"", "\\\"" ); + std::string symbol = replace ( factory::StringDataFactory::toString ( string::stringFrom(transition.first.second )), "\"", "\\\"" ); - 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 6eafcab2757a9b080ee9638e1ea876622309b6a5..88e5214e450ffdbc7c97986dea335e6f7a53ca91 100644 --- a/alib2aux/src/convert/TikZConverter.h +++ b/alib2aux/src/convert/TikZConverter.h @@ -939,26 +939,24 @@ void TikZConverter::transitions ( const automaton::CompactNFA < SymbolType, Stat for ( const auto & transition : fsm.getTransitions ( ) ) { std::string symbol = replace ( factory::StringDataFactory::toString ( string::stringFrom ( transition.first.second ) ), "\"", "\\\"" ); - 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 a6d71301f7131f35e3d3da470b1f72c71ef6107a..62fff57b1e2b679a615e9ccbc1ce5d424b8e7664 100644 --- a/alib2data/src/automaton/FSM/CompactNFA.h +++ b/alib2data/src/automaton/FSM/CompactNFA.h @@ -27,7 +27,7 @@ #include <ostream> #include <sstream> -#include <alib/map> +#include <alib/multimap> #include <alib/set> #include <alib/algorithm> #include <alib/compare> @@ -81,7 +81,7 @@ class CompactNFA final : public ext::CompareOperators < CompactNFA < SymbolType, /** * Transition function as mapping from a state times a list of input symbols on the left hand side to a set of states. */ - ext::map < ext::pair < StateType, ext::vector < SymbolType > >, ext::set < StateType > > transitions; + ext::multimap < ext::pair < StateType, ext::vector < SymbolType > >, StateType > transitions; public: /** @@ -349,19 +349,6 @@ public: */ bool addTransition ( StateType current, ext::vector < SymbolType > input, StateType next ); - /** - * \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 list of input symbols (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 current, ext::vector < SymbolType > input, ext::set < StateType > next ); - /** * \brief Removes a transition from the automaton. * @@ -380,14 +367,14 @@ public: * * \returns transition function of the automaton */ - const ext::map < ext::pair < StateType, ext::vector < SymbolType > >, ext::set < StateType > > & getTransitions ( ) const &; + const ext::multimap < ext::pair < StateType, ext::vector < 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::vector < SymbolType > >, ext::set < StateType > > && getTransitions ( ) &&; + ext::multimap < ext::pair < StateType, ext::vector < SymbolType > >, StateType > && getTransitions ( ) &&; /** * Get a subset of the transition function of the automaton, with the source state fixed in the transitions natural representation. @@ -396,7 +383,7 @@ public: * * \returns a subset of the transition function of the automaton with the source state fixed */ - ext::map < ext::pair < StateType, ext::vector < SymbolType > >, ext::set < StateType > > getTransitionsFromState ( const StateType & from ) const; + ext::multimap < ext::pair < StateType, ext::vector < SymbolType > >, StateType > getTransitionsFromState ( const StateType & from ) const; /** * Get a subset of the transition function of the automaton, with the target state fixed in the transitions natural representation. @@ -405,7 +392,7 @@ public: * * \returns a subset of the transition function of the automaton with the target state fixed */ - ext::map < ext::pair < StateType, ext::vector < SymbolType > >, ext::set < StateType > > getTransitionsToState ( const StateType & from ) const; + ext::multimap < ext::pair < StateType, ext::vector < SymbolType > >, StateType > getTransitionsToState ( const StateType & from ) const; /** * The actual compare method @@ -454,12 +441,14 @@ 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 ( ) ) - 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 ); - - transitions.insert ( ext::make_pair ( this->getInitialState ( ), ext::vector < SymbolType > { } ), other.getInitialStates ( ) ); + 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 ); + + for ( const auto & state : other.getInitialStates ( ) ) + transitions.insert ( ext::make_pair ( this->getInitialState ( ), ext::vector < SymbolType > { } ), state ); } template < class SymbolType, class StateType > @@ -467,35 +456,36 @@ 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 [ ext::make_pair ( transition.first.first, ext::vector < SymbolType > { } ) ].insert ( transition.second ); + transitions.insert ( ext::make_pair ( transition.first.first, ext::vector < SymbolType > { } ), transition.second ); else - transitions [ ext::make_pair ( transition.first.first, ext::vector < SymbolType > { transition.first.second.template get < SymbolType > ( ) } ) ].insert ( transition.second ); + transitions.insert ( ext::make_pair ( transition.first.first, ext::vector < SymbolType > { transition.first.second.template get < SymbolType > ( ) } ), transition.second ); } template < class SymbolType, class StateType > CompactNFA < SymbolType, StateType >::CompactNFA ( const MultiInitialStateNFA < SymbolType, 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 ( ) ) - transitions [ ext::make_pair ( transition.first.first, ext::vector < SymbolType > { transition.first.second } ) ].insert ( transition.second ); + transitions.insert ( ext::make_pair ( transition.first.first, ext::vector < SymbolType > { transition.first.second } ), transition.second ); - transitions.insert ( ext::make_pair ( this->getInitialState ( ), ext::vector < SymbolType > { } ), other.getInitialStates ( ) ); + for ( const auto & state : other.getInitialStates ( ) ) + transitions.insert ( ext::make_pair ( this->getInitialState ( ), ext::vector < SymbolType > { } ), state ); } template < class SymbolType, class StateType > CompactNFA < SymbolType, StateType >::CompactNFA ( const NFA < SymbolType, StateType > & other ) : CompactNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) { for ( const auto & transition : other.getTransitions ( ) ) - transitions [ ext::make_pair ( transition.first.first, ext::vector < SymbolType > { transition.first.second } ) ].insert ( transition.second ); + transitions.insert ( ext::make_pair ( transition.first.first, ext::vector < SymbolType > { transition.first.second } ), transition.second ); } 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 ( ext::make_pair ( transition.first.first, transition.first.second ), ext::set < StateType > { transition.second } ); + transitions.insert ( transition ); } template < class SymbolType, class StateType > CompactNFA < SymbolType, StateType >::CompactNFA ( const DFA < SymbolType, StateType > & other ) : CompactNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) { for ( const auto & transition : other.getTransitions ( ) ) - transitions [ ext::make_pair ( transition.first.first, ext::vector < SymbolType > { transition.first.second } ) ].insert ( transition.second ); + transitions.insert ( ext::make_pair ( transition.first.first, ext::vector < SymbolType > { transition.first.second } ), transition.second ); } template < class SymbolType, class StateType > @@ -512,71 +502,63 @@ bool CompactNFA < SymbolType, StateType >::addTransition ( StateType from, ext:: if ( !getStates ( ).count ( to ) ) throw AutomatonException ( "State \"" + ext::to_string ( to ) + "\" doesn't exist." ); - ext::pair < StateType, ext::vector < SymbolType > > key = ext::make_pair ( std::move ( from ), std::move ( input ) ); - - return transitions[std::move ( key )].insert ( std::move ( to ) ).second; -} - -template < class SymbolType, class StateType > -void CompactNFA < SymbolType, StateType >::addTransitions ( StateType from, ext::vector < SymbolType > input, ext::set < StateType > to ) { - if ( !getStates ( ).count ( from ) ) - throw AutomatonException ( "State \"" + ext::to_string ( from ) + "\" doesn't exist." ); - - ext::set < SymbolType > inputStringAlphabet ( input.begin ( ), input.end ( ) ); - - // Transition regexp's alphabet must be subset of automaton's alphabet - if ( !std::includes ( getInputAlphabet ( ).begin ( ), getInputAlphabet ( ).end ( ), inputStringAlphabet.begin ( ), inputStringAlphabet.end ( ) ) ) - throw AutomatonException ( "Input string is over different alphabet than automaton" ); - - if ( !std::includes ( getStates ( ).begin ( ), getStates ( ).end ( ), to.begin ( ), to.end ( ) ) ) - throw AutomatonException ( "Some target states don't exist." ); + 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; ext::pair < StateType, ext::vector < 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 ( ) ); + transitions.insert ( iter, std::make_pair ( std::move ( key ), std::move ( to ) ) ); + return true; } template < class SymbolType, class StateType > bool CompactNFA < SymbolType, StateType >::removeTransition ( const StateType & from, const ext::vector < SymbolType > & input, const StateType & to ) { - ext::pair < StateType, ext::vector < SymbolType > > key = std::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 > -const ext::map < ext::pair < StateType, ext::vector < SymbolType > >, ext::set < StateType > > & CompactNFA < SymbolType, StateType >::getTransitions ( ) const & { +const ext::multimap < ext::pair < StateType, ext::vector < SymbolType > >, StateType > & CompactNFA < SymbolType, StateType >::getTransitions ( ) const & { return transitions; } template < class SymbolType, class StateType > -ext::map < ext::pair < StateType, ext::vector < SymbolType > >, ext::set < StateType > > && CompactNFA < SymbolType, StateType >::getTransitions ( ) && { +ext::multimap < ext::pair < StateType, ext::vector < SymbolType > >, StateType > && CompactNFA < SymbolType, StateType >::getTransitions ( ) && { return std::move ( transitions ); } template < class SymbolType, class StateType > -ext::map < ext::pair < StateType, ext::vector < SymbolType > >, ext::set < StateType > > CompactNFA < SymbolType, StateType >::getTransitionsFromState ( const StateType & from ) const { +ext::multimap < ext::pair < StateType, ext::vector < SymbolType > >, StateType > CompactNFA < SymbolType, 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::vector < SymbolType > >, ext::set < StateType > > transitionsFromState; + ext::multimap < ext::pair < StateType, ext::vector < SymbolType > >, StateType > transitionsFromState; - for ( const std::pair < const ext::pair < StateType, ext::vector < SymbolType > >, ext::set < StateType > > & transition : transitions ) + for ( const std::pair < const ext::pair < StateType, ext::vector < SymbolType > >, StateType > & transition : transitions ) if ( transition.first.first == from ) - transitionsFromState.insert ( transition.first, transition.second ); + transitionsFromState.insert ( transition ); return transitionsFromState; } template < class SymbolType, class StateType > -ext::map < ext::pair < StateType, ext::vector < SymbolType > >, ext::set < StateType > > CompactNFA < SymbolType, StateType >::getTransitionsToState ( const StateType & to ) const { +ext::multimap < ext::pair < StateType, ext::vector < SymbolType > >, StateType > CompactNFA < SymbolType, 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::vector < SymbolType > >, ext::set < StateType > > transitionsToState; + ext::multimap < ext::pair < StateType, ext::vector < SymbolType > >, StateType > transitionsToState; - for ( const std::pair < const ext::pair < StateType, ext::vector < 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::vector < SymbolType > >, StateType > & transition : transitions ) + if ( transition.second == to ) + transitionsToState.insert ( transition ); return transitionsToState; } @@ -620,7 +602,7 @@ public: * \returns true if the symbol is used, false othervise */ static bool used ( const automaton::CompactNFA < SymbolType, StateType > & automaton, const SymbolType & symbol ) { - for ( const std::pair < const ext::pair < StateType, ext::vector < SymbolType > >, ext::set < StateType > > & transition : automaton.getTransitions ( ) ) { + for ( const std::pair < const ext::pair < StateType, ext::vector < SymbolType > >, StateType > & transition : automaton.getTransitions ( ) ) { ext::set < SymbolType > alphabet ( transition.first.second.begin ( ), transition.first.second.end ( ) ); if ( alphabet.count ( symbol ) ) return true; @@ -675,8 +657,8 @@ public: if ( automaton.getFinalStates ( ).count ( state ) ) return true; - for ( const std::pair < const ext::pair < StateType, ext::vector < SymbolType > >, ext::set < StateType > > & t : automaton.getTransitions ( ) ) - if ( ( t.first.first == state ) || t.second.count ( state ) ) + for ( const std::pair < const ext::pair < StateType, ext::vector < SymbolType > >, StateType > & t : automaton.getTransitions ( ) ) + if ( t.first.first == state || t.second == state ) return true; return false; @@ -793,12 +775,12 @@ struct normalize < automaton::CompactNFA < SymbolType, StateType > > { automaton::CompactNFA < > res ( std::move ( states ), std::move ( alphabet ), std::move ( initialState ), std::move ( finalStates ) ); - for ( std::pair < ext::pair < StateType, ext::vector < SymbolType > >, ext::set < StateType > > && transition : ext::make_mover ( std::move ( value ).getTransitions ( ) ) ) { + for ( std::pair < ext::pair < StateType, ext::vector < SymbolType > >, StateType > && transition : ext::make_mover ( std::move ( value ).getTransitions ( ) ) ) { DefaultStateType from = automaton::AutomatonNormalize::normalizeState ( std::move ( transition.first.first ) ); ext::vector < DefaultSymbolType > input = alphabet::SymbolNormalize::normalizeSymbols ( 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 2315673b7e72a34ddd392c93b73285376c97cd30..96256abb066f873b01b8ee1783579861f8757c0f 100644 --- a/alib2data/src/automaton/FSM/ExtendedNFA.h +++ b/alib2data/src/automaton/FSM/ExtendedNFA.h @@ -448,8 +448,7 @@ ExtendedNFA < SymbolType, StateType >::ExtendedNFA ( const CompactNFA < SymbolTy con.appendElement ( regexp::UnboundedRegExpSymbol < SymbolType > ( symbol ) ); ext::pair < StateType, regexp::UnboundedRegExpStructure < SymbolType > > key = ext::make_pair ( transition.first.first, regexp::UnboundedRegExpStructure < SymbolType > ( std::move ( con ) ) ); - for ( const StateType & to : transition.second ) - transitions.insert ( key, to ); + transitions.insert ( key, transition.second ); } } template < class SymbolType, class StateType > diff --git a/alib2data/src/automaton/xml/FSM/CompactNFA.h b/alib2data/src/automaton/xml/FSM/CompactNFA.h index ccaf326dcd3a029f17e2e48e75269fb67fbc3cfa..7409538b8392bcddd4b69bdbd99c23acf7524e7e 100644 --- a/alib2data/src/automaton/xml/FSM/CompactNFA.h +++ b/alib2data/src/automaton/xml/FSM/CompactNFA.h @@ -138,16 +138,15 @@ template < class SymbolType, class StateType > void xmlApi < automaton::CompactNFA < SymbolType, StateType > >::composeTransitions ( ext::deque < sax::Token > & out, const automaton::CompactNFA < SymbolType, 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::composeTransitionInputSymbolMultiple ( out, transition.first.second ); - automaton::AutomatonToXMLComposer::composeTransitionTo ( out, targetState ); + automaton::AutomatonToXMLComposer::composeTransitionFrom ( out, transition.first.first ); + automaton::AutomatonToXMLComposer::composeTransitionInputSymbolMultiple ( 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/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h index 09fe2c767ab5417a2f90b815c114d5f3e2cbef4e..049717011fc7ac269f7150edd758480c35e19e86 100644 --- a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h +++ b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h @@ -152,10 +152,9 @@ ext::map<StateType, ext::set<StateType>> AllEpsilonClosure::allEpsilonClosure( c ext::set<StateType> nonvisited = fsm.getStates(); ext::multimap<StateType, StateType > epsilonTransitions; - for(const std::pair<const ext::pair<StateType, ext::vector < SymbolType > >, ext::set<StateType> >& transition : fsm.getTransitions() ) + for(const std::pair<const ext::pair<StateType, ext::vector < SymbolType > >, StateType >& transition : fsm.getTransitions() ) if( transition.first.second.size() == 0 ) - for ( const auto & to : transition.second ) - epsilonTransitions.insert ( transition.first.first, to ); + epsilonTransitions.insert ( transition.first.first, transition.second ); 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 fe435ae79d188905dbb929427bc1042c5c00809a..3b7766b509c03702adceaac0823dca45db34d96e 100644 --- a/alib2elgo/src/automaton/properties/efficient/ReachableStates.h +++ b/alib2elgo/src/automaton/properties/efficient/ReachableStates.h @@ -35,8 +35,6 @@ public: static ext::set < typename automaton::StateTypeOfAutomaton < T > > reachableStates( const T & fsm ); template < class SymbolType, class StateType > static ext::set<StateType> reachableStates( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm ); - template < class SymbolType, class StateType > - static ext::set<StateType> reachableStates( const automaton::CompactNFA < SymbolType, StateType > & fsm ); }; template < class T > @@ -85,28 +83,6 @@ ext::set<StateType> ReachableStates::reachableStates( const automaton::MultiInit return visited; } -template < class SymbolType, class StateType > -ext::set<StateType> ReachableStates::reachableStates( const automaton::CompactNFA < SymbolType, StateType > & fsm ) { - ext::map<StateType, ext::set<StateType>> transitions; - for(const auto& transition : fsm.getTransitions()) - transitions[transition.first.first].insert(transition.second.begin ( ), transition.second.end ( )); - - 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; -} - } /* namespace efficient */ } /* namespace properties */ diff --git a/alib2elgo/src/automaton/properties/efficient/UsefulStates.h b/alib2elgo/src/automaton/properties/efficient/UsefulStates.h index d892130406b83db539cf3c293024eaa5646afcb8..20ab8c3d7328ef2b2df1c0e4614cf3ef2a949600 100644 --- a/alib2elgo/src/automaton/properties/efficient/UsefulStates.h +++ b/alib2elgo/src/automaton/properties/efficient/UsefulStates.h @@ -34,8 +34,6 @@ public: template < class T > static ext::set < typename automaton::StateTypeOfAutomaton < T > > usefulStates( const T & fsm ); template < class SymbolType, class StateType > - static ext::set<StateType> usefulStates( const automaton::CompactNFA < SymbolType, StateType > & fsm ); - template < class SymbolType, class StateType > static ext::set<StateType> usefulStates( const automaton::ExtendedNFA < SymbolType, StateType > & fsm ); }; @@ -85,29 +83,6 @@ ext::set<StateType> UsefulStates::usefulStates( const automaton::ExtendedNFA < S return visited; } -template < class SymbolType, class StateType > -ext::set<StateType> UsefulStates::usefulStates( const automaton::CompactNFA < SymbolType, StateType > & fsm ) { - ext::map<StateType, ext::set<StateType>> reversedTransitions; - for(const auto& transition : fsm.getTransitions()) - for(const StateType& to : transition.second) - reversedTransitions[to].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; -} - } /* namespace efficient */ } /* namespace properties */ diff --git a/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h b/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h index 0bcdb56d2f2d53cbcecc512d45244976b9554e4e..522b31a98906cf0ea1807f015afa7eaf31fe8843 100644 --- a/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h +++ b/alib2elgo/src/automaton/simplify/efficient/UnreachableStatesRemover.h @@ -35,8 +35,6 @@ public: template < class T > static T remove( const T & automaton ); template < class SymbolType, class StateType > - static automaton::CompactNFA < SymbolType, StateType > remove( const automaton::CompactNFA < SymbolType, StateType > & fsm ); - template < class SymbolType, class StateType > static automaton::MultiInitialStateNFA < SymbolType, StateType > remove( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm ); }; @@ -68,33 +66,6 @@ T UnreachableStatesRemover::remove ( const T & fsm ) { return M; } -template < class SymbolType, class StateType > -automaton::CompactNFA < SymbolType, StateType > UnreachableStatesRemover::remove( const automaton::CompactNFA < SymbolType, StateType > & fsm ) { - // 1a - ext::set<StateType> Qa = automaton::properties::efficient::ReachableStates::reachableStates( fsm ); - - // 2 - automaton::CompactNFA < SymbolType, 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 ) ) - for(const auto& to : transition.second ) - M.addTransition( transition.first.first, transition.first.second, to ); - - 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::MultiInitialStateNFA < SymbolType, StateType > UnreachableStatesRemover::remove( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm ) { // 1a diff --git a/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h b/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h index cdbd48858cd0dd51d4a014c8185ec62ac2fca81e..b0c59b3494624335fcf79c4ffb4ebf7fa5e2f21d 100644 --- a/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h +++ b/alib2elgo/src/automaton/simplify/efficient/UselessStatesRemover.h @@ -35,8 +35,6 @@ public: template < class T > static T remove( const T & automaton ); template < class SymbolType, class StateType > - static automaton::CompactNFA < SymbolType, StateType > remove( const automaton::CompactNFA < SymbolType, StateType > & fsm ); - template < class SymbolType, class StateType > static automaton::MultiInitialStateNFA < SymbolType, StateType > remove( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm ); }; @@ -70,35 +68,6 @@ T UselessStatesRemover::remove( const T & fsm ) { return M; } -template < class SymbolType, class StateType > -automaton::CompactNFA < SymbolType, StateType > UselessStatesRemover::remove( const automaton::CompactNFA < SymbolType, StateType > & fsm ) { - // 1. - ext::set<StateType> Qu = automaton::properties::efficient::UsefulStates::usefulStates( fsm ); - - // 2. - automaton::CompactNFA < SymbolType, 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( ) ) - for( const auto & to : t.second ) - if( /* this part is not needed Qu.count(t.first.first) ) && */ Qu.count(to) ) - M.addTransition( t.first.first, t.first.second, to ); - - for( const auto & q : fsm.getFinalStates( ) ) - M.addFinalState( q ); - - return M; -} - template < class SymbolType, class StateType > automaton::MultiInitialStateNFA < SymbolType, StateType > UselessStatesRemover::remove( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm ) { // 1.