From dc65d4b1f2166ead09341989c2e148e62278a95c Mon Sep 17 00:00:00 2001 From: Jan Travnicek <jan.travnicek@.fit.cvut.cz> Date: Wed, 27 Mar 2019 15:22:53 +0100 Subject: [PATCH] redesign trim FTA --- .../automaton/properties/ReachableStates.cpp | 14 +++ .../automaton/properties/ReachableStates.h | 80 ++++++++++++ .../src/automaton/properties/UsefulStates.cpp | 14 +++ .../src/automaton/properties/UsefulStates.h | 80 ++++++++++++ alib2algo/src/automaton/simplify/Trim.cpp | 12 +- alib2algo/src/automaton/simplify/Trim.h | 2 +- .../simplify/UnreachableStatesRemover.cpp | 10 +- .../simplify/UnreachableStatesRemover.h | 117 ++++++++++-------- .../simplify/UselessStatesRemover.cpp | 10 +- .../automaton/simplify/UselessStatesRemover.h | 84 +++++++++---- alib2data/src/automaton/TA/DFTA.h | 28 +++++ alib2data/src/automaton/TA/NFTA.h | 27 ++++ 12 files changed, 392 insertions(+), 86 deletions(-) diff --git a/alib2algo/src/automaton/properties/ReachableStates.cpp b/alib2algo/src/automaton/properties/ReachableStates.cpp index f04c3130c9..c2c59cd948 100644 --- a/alib2algo/src/automaton/properties/ReachableStates.cpp +++ b/alib2algo/src/automaton/properties/ReachableStates.cpp @@ -54,6 +54,20 @@ Using closure implementation of the BFS algorithm.\n\ @param fsm automaton\n\ @return set of reachable states from the initial state of @p fsm" ); +auto ReachableStatesDFTA = registration::AbstractRegister < ReachableStates, ext::set < DefaultStateType >, const automaton::DFTA < > & > ( ReachableStates::reachableStates, "fta" ).setDocumentation ( +"Finds all reachable states of a finite tree automaton.\n\ +Using closure implementation of the BFS algorithm.\n\ +\n\ +@param fta automaton\n\ +@return set of reachable states from states that read leaves of @p fta" ); + +auto ReachableStatesNFTA = registration::AbstractRegister < ReachableStates, ext::set < DefaultStateType >, const automaton::NFTA < > & > ( ReachableStates::reachableStates, "fta" ).setDocumentation ( +"Finds all reachable states of a finite tree automaton.\n\ +Using closure implementation of the BFS algorithm.\n\ +\n\ +@param fta automaton\n\ +@return set of reachable states from states that read leaves of @p fta" ); + } /* namespace properties */ } /* namespace automaton */ diff --git a/alib2algo/src/automaton/properties/ReachableStates.h b/alib2algo/src/automaton/properties/ReachableStates.h index 215cbb3d6c..4c95a48761 100644 --- a/alib2algo/src/automaton/properties/ReachableStates.h +++ b/alib2algo/src/automaton/properties/ReachableStates.h @@ -34,6 +34,8 @@ #include <automaton/FSM/EpsilonNFA.h> #include <automaton/FSM/NFA.h> #include <automaton/FSM/DFA.h> +#include <automaton/TA/DFTA.h> +#include <automaton/TA/NFTA.h> #include <automaton/Automaton.h> @@ -85,6 +87,34 @@ public: */ template < class SymbolType, class StateType > static ext::set<StateType> reachableStates( const automaton::DFA < 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 nondeterministic automaton with multiple initial states + * @return set of reachable states from the initial state of @p fsm + */ + template < class SymbolType, class RankType, class StateType > + static ext::set<StateType> reachableStates( const automaton::DFTA < SymbolType, RankType, StateType > & fta ); + + /** + * 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 nondeterministic automaton with multiple initial states + * @return set of reachable states from the initial state of @p fsm + */ + template < class SymbolType, class RankType, class StateType > + static ext::set<StateType> reachableStates( const automaton::NFTA < SymbolType, RankType, StateType > & fta ); }; template < class T > @@ -167,6 +197,56 @@ ext::set<StateType> ReachableStates::reachableStates( const automaton::DFA < Sym return Qi.at( i ); } +template < class SymbolType, class RankType, class StateType > +ext::set<StateType> ReachableStates::reachableStates( const automaton::DFTA < SymbolType, RankType, StateType > & fta ) { + // 1a + ext::deque<ext::set<StateType>> Qi; + Qi.push_back( ext::set<StateType>( ) ); + + int i = 1; + + // 1bc + while( true ) { + Qi.push_back( Qi.at( i - 1 ) ); + + for( const auto & transition : fta.getTransitions ( ) ) + if ( std::all_of ( transition.first.second.begin ( ), transition.first.second.end ( ), [ & ] ( const StateType & state ) { return Qi.at ( i - 1 ).count ( state ); } ) ) + 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::NFTA < SymbolType, RankType, StateType > & fta ) { + // 1a + ext::deque<ext::set<StateType>> Qi; + Qi.push_back( ext::set<StateType>( ) ); + + int i = 1; + + // 1bc + while( true ) { + Qi.push_back( Qi.at( i - 1 ) ); + + for( const auto & transition : fta.getTransitions ( ) ) + if ( std::all_of ( transition.first.second.begin ( ), transition.first.second.end ( ), [ & ] ( const StateType & state ) { return Qi.at ( i - 1 ).count ( state ); } ) ) + 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 ); +} + } /* namespace properties */ } /* namespace automaton */ diff --git a/alib2algo/src/automaton/properties/UsefulStates.cpp b/alib2algo/src/automaton/properties/UsefulStates.cpp index c99e381d10..33a719d374 100644 --- a/alib2algo/src/automaton/properties/UsefulStates.cpp +++ b/alib2algo/src/automaton/properties/UsefulStates.cpp @@ -54,6 +54,20 @@ Using closure implementation of the BFS algorithm.\n\ @param fsm automaton\n\ @return set of useful states of @p fsm" ); +auto UsefulStatesDFTA = registration::AbstractRegister < UsefulStates, ext::set < DefaultStateType >, const automaton::DFTA < > & > ( UsefulStates::usefulStates, "fta" ).setDocumentation ( +"Finds all useful states of a finite tree automaton.\n\ +Using closure implementation of the BFS algorithm.\n\ +\n\ +@param fta automaton\n\ +@return set of useful states of @p fta" ); + +auto UsefulStatesNFTA = registration::AbstractRegister < UsefulStates, ext::set < DefaultStateType >, const automaton::NFTA < > & > ( UsefulStates::usefulStates, "fta" ).setDocumentation ( +"Finds all useful states of a finite tree automaton.\n\ +Using closure implementation of the BFS algorithm.\n\ +\n\ +@param fta automaton\n\ +@return set of useful states of @p fta" ); + } /* namespace properties */ } /* namespace automaton */ diff --git a/alib2algo/src/automaton/properties/UsefulStates.h b/alib2algo/src/automaton/properties/UsefulStates.h index a036d7a215..e5632916ee 100644 --- a/alib2algo/src/automaton/properties/UsefulStates.h +++ b/alib2algo/src/automaton/properties/UsefulStates.h @@ -34,6 +34,8 @@ #include <automaton/FSM/EpsilonNFA.h> #include <automaton/FSM/NFA.h> #include <automaton/FSM/DFA.h> +#include <automaton/TA/DFTA.h> +#include <automaton/TA/NFTA.h> #include <automaton/Automaton.h> @@ -71,6 +73,36 @@ public: */ template < class SymbolType, class StateType > static ext::set<StateType> usefulStates( const automaton::DFA < SymbolType, StateType > & fsm ); + + /** + * Finds all useful states of a deterministic finite tree automaton. + * Using closure implementation of the BFS algorithm. + * + * @overload + * + * @tparam SymbolType Type for the input symbols. + * @tparam RankType Type of ranks in the automaton. + * @tparam StateType Type for the states. + * @param fta automaton + * @return set of useful states of @p fta + */ + template < class SymbolType, class RankType, class StateType > + static ext::set<StateType> usefulStates( const automaton::DFTA < SymbolType, RankType, StateType > & fta ); + + /** + * Finds all useful states of a deterministic finite tree automaton. + * Using closure implementation of the BFS algorithm. + * + * @overload + * + * @tparam SymbolType Type for the input symbols. + * @tparam RankType Type of ranks in the automaton. + * @tparam StateType Type for the states. + * @param fta automaton + * @return set of useful states of @p fta + */ + template < class SymbolType, class RankType, class StateType > + static ext::set<StateType> usefulStates( const automaton::NFTA < SymbolType, RankType, StateType > & fta ); }; template < class T > @@ -123,6 +155,54 @@ ext::set<StateType> UsefulStates::usefulStates( const automaton::DFA < SymbolTyp return Qi.at( i ); } +template < class SymbolType, class RankType, class StateType > +ext::set<StateType> UsefulStates::usefulStates( const automaton::DFTA < SymbolType, RankType, StateType > & fta ) { + // 1a + ext::deque<ext::set<StateType>> Qi; + Qi.push_back( ext::set<StateType>( ) ); + Qi.at( 0 ) = fta.getFinalStates( ); + + int i = 1; + + // 1bc + while( true ) { + Qi.push_back( Qi.at( i - 1 ) ); // copy Qi-1 into Qi + for( const auto & p : Qi.at( i - 1 ) ) + for( const auto & t : fta.getTransitionsToState ( p ) ) + Qi.at( i ).insert( t.first.second.begin ( ), t.first.second.end ( ) ); + + 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> UsefulStates::usefulStates( const automaton::NFTA < SymbolType, RankType, StateType > & fta ) { + // 1a + ext::deque<ext::set<StateType>> Qi; + Qi.push_back( ext::set<StateType>( ) ); + Qi.at( 0 ) = fta.getFinalStates( ); + + int i = 1; + + // 1bc + while( true ) { + Qi.push_back( Qi.at( i - 1 ) ); // copy Qi-1 into Qi + for( const auto & p : Qi.at( i - 1 ) ) + for( const auto & t : fta.getTransitionsToState ( p ) ) + Qi.at( i ).insert( t.first.second.begin ( ), t.first.second.end ( ) ); + + if( Qi.at( i ) == Qi.at( i - 1 ) ) + break; + + i = i + 1; + } + return Qi.at( i ); +} + } /* namespace properties */ } /* namespace automaton */ diff --git a/alib2algo/src/automaton/simplify/Trim.cpp b/alib2algo/src/automaton/simplify/Trim.cpp index a8596b6216..86cca5753d 100644 --- a/alib2algo/src/automaton/simplify/Trim.cpp +++ b/alib2algo/src/automaton/simplify/Trim.cpp @@ -55,11 +55,17 @@ auto TrimExtendedNFA = registration::AbstractRegister < Trim, automaton::Extende @param fsm finite automaton or finite tree automaton to trim\n\ @return the trimmed automaton equivalent to @p fsm" ); -auto TrimDFTA = registration::AbstractRegister < Trim, automaton::DFTA < >, const automaton::DFTA < > & > ( Trim::trim, "fsm" ).setDocumentation ( +auto TrimDFTA = registration::AbstractRegister < Trim, automaton::DFTA < >, const automaton::DFTA < > & > ( Trim::trim, "fta" ).setDocumentation ( "Removes inaccessible and useless states from the given automaton. Uses first the @sa UselessStatesRemover and next @sa UnreachableStatesRemover in the process.\n\ \n\ -@param fsm finite automaton or finite tree automaton to trim\n\ -@return the trimmed automaton equivalent to @p fsm" ); +@param fta finite tree automaton or finite tree automaton to trim\n\ +@return the trimmed automaton equivalent to @p fta" ); + +auto TrimNFTA = registration::AbstractRegister < Trim, automaton::NFTA < >, const automaton::NFTA < > & > ( Trim::trim, "fta" ).setDocumentation ( +"Removes inaccessible and useless states from the given automaton. Uses first the @sa UselessStatesRemover and next @sa UnreachableStatesRemover in the process.\n\ +\n\ +@param fta finite automaton or finite tree automaton to trim\n\ +@return the trimmed automaton equivalent to @p fta" ); } /* namespace simplify */ diff --git a/alib2algo/src/automaton/simplify/Trim.h b/alib2algo/src/automaton/simplify/Trim.h index ecbb647f72..670c0c73cb 100644 --- a/alib2algo/src/automaton/simplify/Trim.h +++ b/alib2algo/src/automaton/simplify/Trim.h @@ -55,7 +55,7 @@ public: template < class T > T Trim::trim ( const T & fsm ) { - return UnreachableStatesRemover::remove ( UselessStatesRemover::remove ( fsm ) ); + return UselessStatesRemover::remove ( UnreachableStatesRemover::remove ( fsm ) ); } } /* namespace simplify */ diff --git a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp index bd22bba1b9..ccf9d5676b 100644 --- a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp +++ b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.cpp @@ -48,10 +48,16 @@ auto UnreachableStatesRemoverMultiInitialStateNFA = registration::AbstractRegist @param automaton automaton to trim\n\ @return @p automaton without unreachable states" ); -auto UnreachableStatesRemoverDFTA = registration::AbstractRegister < UnreachableStatesRemover, automaton::DFTA < >, const automaton::DFTA < > & > ( UnreachableStatesRemover::remove, "dfta" ).setDocumentation ( +auto UnreachableStatesRemoverDFTA = registration::AbstractRegister < UnreachableStatesRemover, automaton::DFTA < >, const automaton::DFTA < > & > ( UnreachableStatesRemover::remove, "fta" ).setDocumentation ( "Removes unreachable states from a deterministic finite tree automaton.\n\ \n\ -@param dfta automaton to trim\n\ +@param fta automaton to trim\n\ +@return @p autoamton without unreachable states" ); + +auto UnreachableStatesRemoverNFTA = registration::AbstractRegister < UnreachableStatesRemover, automaton::NFTA < >, const automaton::NFTA < > & > ( UnreachableStatesRemover::remove, "fta" ).setDocumentation ( +"Removes unreachable states from a deterministic finite tree automaton.\n\ +\n\ +@param fta automaton to trim\n\ @return @p autoamton without unreachable states" ); } /* namespace simplify */ diff --git a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h index 3bbaaf48a9..f7451af96e 100644 --- a/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h +++ b/alib2algo/src/automaton/simplify/UnreachableStatesRemover.h @@ -94,6 +94,22 @@ public: */ template < class SymbolType, class RankType, class StateType > static automaton::DFTA < SymbolType, RankType, StateType > remove( const automaton::DFTA < SymbolType, RankType, StateType > & dfta ); + + /** + * Removes unreachable states from a deterministic finite tree automaton. + * + * @overload + * + * @tparam SymbolType Type for input symbols. + * @tparam RankType Type for rank (arity) in ranked alphabet. + * @tparam StateType Type for states. + * + * @param dfta automaton to trim + * + * @return @p autoamton without unreachable states + */ + template < class SymbolType, class RankType, class StateType > + static automaton::NFTA < SymbolType, RankType, StateType > remove( const automaton::NFTA < SymbolType, RankType, StateType > & dfta ); }; template < class T > @@ -181,58 +197,55 @@ automaton::MultiInitialStateNFA < SymbolType, StateType > UnreachableStatesRemov } template < class SymbolType, class RankType, class StateType > -automaton::DFTA < SymbolType, RankType, StateType > UnreachableStatesRemover::remove( const automaton::DFTA < SymbolType, RankType, StateType > & dfta ) { - automaton::DFTA < SymbolType, RankType, StateType > res; - res.setInputAlphabet(dfta.getInputAlphabet()); - - typedef std::pair < const ext::pair < common::ranked_symbol < SymbolType, RankType >, ext::vector < StateType > >, StateType > Transition; - ext::vector<ext::pair<const Transition *, int>> transitionsUnreachableCount; - transitionsUnreachableCount.reserve(dfta.getTransitions().size()); - - //for a state, transitions with unreachable count (initially all unreachable) and number of occurences of this state (at least 1) - ext::map<StateType, ext::map<ext::pair<const Transition *, int> *, int>> stateOccurences; - ext::deque<StateType> queue; - for(const auto & transition : dfta.getTransitions()) { - if (transition.first.second.empty()) { - queue.push_back(transition.second); - res.addState(transition.second); - res.addTransition(transition.first.first, transition.first.second, transition.second); - } else { - transitionsUnreachableCount.push_back({&transition, transition.first.second.size()}); - for (const auto & state : transition.first.second) { - auto & occurences = stateOccurences[state]; - auto it = occurences.find(&transitionsUnreachableCount.back()); - if (it == occurences.end()) occurences[&transitionsUnreachableCount.back()] = 1; - else it->second++; - } - } - } - - while(!queue.empty()) { - const auto & occurences = stateOccurences[queue.front()]; - queue.pop_front(); - for (const auto & occurence : occurences) { - int & unreachableCount = occurence.first -> second; - const StateType & to = occurence.first -> first -> second; - unreachableCount -= occurence.second; - if (unreachableCount == 0) { - if (res.addState(to)) { - queue.push_back(to); - } - } - } - } - - for (const auto & state : res.getStates()) { - if (dfta.getFinalStates().count(state) != 0) res.addFinalState(state); - } - for (const auto & transitionUnreachableCount : transitionsUnreachableCount) { - if (transitionUnreachableCount.second == 0) { - const Transition transition = *(transitionUnreachableCount.first); - res.addTransition(transition.first.first, transition.first.second, transition.second); - } - } - return res; +automaton::DFTA < SymbolType, RankType, StateType > UnreachableStatesRemover::remove( const automaton::DFTA < SymbolType, RankType, StateType > & fta ) { + // 1a + ext::set<StateType> Qa = automaton::properties::ReachableStates::reachableStates( fta ); + + // 2 + automaton::DFTA < SymbolType, RankType, StateType > M; + + for( const auto & q : Qa ) + M.addState( q ); + + for( const auto & a : fta.getInputAlphabet( ) ) + M.addInputSymbol( a ); + + for( const auto & transition : fta.getTransitions( ) ) + if( std::all_of ( transition.first.second.begin ( ), transition.first.second.end ( ), [ & ] ( const StateType & state ) { return Qa.count ( state ); } ) ) + M.addTransition ( transition.first.first, transition.first.second, transition.second ); + + ext::set<StateType> intersect; + std::set_intersection( fta.getFinalStates( ).begin(), fta.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 RankType, class StateType > +automaton::NFTA < SymbolType, RankType, StateType > UnreachableStatesRemover::remove( const automaton::NFTA < SymbolType, RankType, StateType > & fta ) { + // 1a + ext::set<StateType> Qa = automaton::properties::ReachableStates::reachableStates( fta ); + + // 2 + automaton::NFTA < SymbolType, RankType, StateType > M; + + for( const auto & q : Qa ) + M.addState( q ); + + for( const auto & a : fta.getInputAlphabet( ) ) + M.addInputSymbol( a ); + + for( const auto & transition : fta.getTransitions( ) ) + if( std::all_of ( transition.first.second.begin ( ), transition.first.second.end ( ), [ & ] ( const StateType & state ) { return Qa.count ( state ); } ) ) + M.addTransitions ( transition.first.first, transition.first.second, transition.second ); + + ext::set<StateType> intersect; + std::set_intersection( fta.getFinalStates( ).begin(), fta.getFinalStates( ).end(), Qa.begin( ), Qa.end( ), std::inserter( intersect, intersect.begin( ) ) ); + for( auto const & state : intersect ) + M.addFinalState( state ); + + return M; } } /* namespace simplify */ diff --git a/alib2algo/src/automaton/simplify/UselessStatesRemover.cpp b/alib2algo/src/automaton/simplify/UselessStatesRemover.cpp index 0780d0b945..c1768aa3ac 100644 --- a/alib2algo/src/automaton/simplify/UselessStatesRemover.cpp +++ b/alib2algo/src/automaton/simplify/UselessStatesRemover.cpp @@ -48,10 +48,16 @@ auto UselessStatesRemoverMultiInitialStateNFA = registration::AbstractRegister < @param automaton automaton to trim\n\ @return @p automaton without useless states" ); -auto UselessStatesRemoverDFTA = registration::AbstractRegister < UselessStatesRemover, automaton::DFTA < >, const automaton::DFTA < > & > ( UselessStatesRemover::remove, "dfta" ).setDocumentation ( +auto UselessStatesRemoverDFTA = registration::AbstractRegister < UselessStatesRemover, automaton::DFTA < >, const automaton::DFTA < > & > ( UselessStatesRemover::remove, "fta" ).setDocumentation ( "Removes unreachable states from a deterministic finite tree automaton.\n\ \n\ -@param dfta automaton to trim\n\ +@param fta automaton to trim\n\ +@return @p autoamton without unreachable states" ); + +auto UselessStatesRemoverNFTA = registration::AbstractRegister < UselessStatesRemover, automaton::NFTA < >, const automaton::NFTA < > & > ( UselessStatesRemover::remove, "fta" ).setDocumentation ( +"Removes unreachable states from a deterministic finite tree automaton.\n\ +\n\ +@param fta automaton to trim\n\ @return @p autoamton without unreachable states" ); } /* namespace simplify */ diff --git a/alib2algo/src/automaton/simplify/UselessStatesRemover.h b/alib2algo/src/automaton/simplify/UselessStatesRemover.h index d4b386b400..1e1f18c9ce 100644 --- a/alib2algo/src/automaton/simplify/UselessStatesRemover.h +++ b/alib2algo/src/automaton/simplify/UselessStatesRemover.h @@ -87,6 +87,19 @@ public: */ template < class SymbolType, class RankType, class StateType > static automaton::DFTA < SymbolType, RankType, StateType > remove( const automaton::DFTA < SymbolType, RankType, StateType > & dfta ); + + /** + * Removes unreachable states from a deterministic finite tree automaton. + * + * @overload + * @tparam SymbolType Type for input symbols. + * @tparam RankType Type for rank (arity) in ranked alphabet. + * @tparam StateType Type for states. + * @param dfta automaton to trim + * @return @p autoamton without unreachable states + */ + template < class SymbolType, class RankType, class StateType > + static automaton::NFTA < SymbolType, RankType, StateType > remove( const automaton::NFTA < SymbolType, RankType, StateType > & dfta ); }; template < class T > @@ -183,41 +196,60 @@ automaton::MultiInitialStateNFA < SymbolType, StateType > UselessStatesRemover:: } template < class SymbolType, class RankType, class StateType > -automaton::DFTA < SymbolType, RankType, StateType > UselessStatesRemover::remove( const automaton::DFTA < SymbolType, RankType, StateType > & dfta ) { - automaton::DFTA < SymbolType, RankType, StateType > res; - res.setInputAlphabet(dfta.getInputAlphabet()); - res.setStates(dfta.getFinalStates()); - res.setFinalStates(dfta.getFinalStates()); +automaton::DFTA < SymbolType, RankType, StateType > UselessStatesRemover::remove( const automaton::DFTA < SymbolType, RankType, StateType > & fta ) { + // 1. + ext::set<StateType> Qu = automaton::properties::UsefulStates::usefulStates( fta ); - typedef std::pair < const ext::pair < common::ranked_symbol < SymbolType, RankType >, ext::vector < StateType > >, StateType > Transition; + // 2. + automaton::DFTA < SymbolType, RankType, StateType > M; - ext::map<StateType, ext::set<const Transition *>> transitionsToState; - for(const auto & transition : dfta.getTransitions()) { - transitionsToState[transition.second].insert(&transition); - } + for( const auto & a : fta.getInputAlphabet( ) ) + M.addInputSymbol( a ); - ext::deque<StateType> queue; - for (const auto & state : dfta.getFinalStates()) { - queue.push_back(state); + if(Qu.size() == 0) { + return M; } - while(!queue.empty()) { - ext::set<const Transition *> & transitions = transitionsToState[queue.front()]; - queue.pop_front(); - for (const Transition * transitionPt : transitions) { - const Transition &transition = *transitionPt; + for( const auto & q : Qu ) + M.addState( q ); - for (const auto & state : transition.first.second) { - if (res.addState(state)) { - queue.push_back(state); - } - } + for( const auto & t : fta.getTransitions( ) ) + if( Qu.count( t.second ) ) + M.addTransition( t.first.first, t.first.second, t.second ); - res.addTransition(transition.first.first, transition.first.second, transition.second); - } + for( const auto & q : fta.getFinalStates( ) ) + M.addFinalState( q ); + + return M; +} + +template < class SymbolType, class RankType, class StateType > +automaton::NFTA < SymbolType, RankType, StateType > UselessStatesRemover::remove( const automaton::NFTA < SymbolType, RankType, StateType > & fta ) { + // 1. + ext::set<StateType> Qu = automaton::properties::UsefulStates::usefulStates( fta ); + + // 2. + automaton::NFTA < SymbolType, RankType, StateType > M; + + for( const auto & a : fta.getInputAlphabet( ) ) + M.addInputSymbol( a ); + + if(Qu.size() == 0) { + return M; } - return res; + for( const auto & q : Qu ) + M.addState( q ); + + for( const auto & t : fta.getTransitions( ) ) + for ( const StateType & to : t.second ) + if( Qu.count( to ) ) + M.addTransition( t.first.first, t.first.second, to ); + + for( const auto & q : fta.getFinalStates( ) ) + M.addFinalState( q ); + + return M; } } /* namespace simplify */ diff --git a/alib2data/src/automaton/TA/DFTA.h b/alib2data/src/automaton/TA/DFTA.h index c715f84093..8ee42d8e39 100644 --- a/alib2data/src/automaton/TA/DFTA.h +++ b/alib2data/src/automaton/TA/DFTA.h @@ -298,6 +298,34 @@ public: return std::move ( transitions ); } + /** + * \returns transitions to state @p q + */ + ext::map < ext::pair < common::ranked_symbol < SymbolType, RankType >, ext::vector < StateType > >, StateType > getTransitionsToState ( const StateType & q ) const { + ext::map < ext::pair < common::ranked_symbol < SymbolType, RankType >, ext::vector < StateType > >, StateType > res; + + for ( const auto & transition : getTransitions ( ) ) { + if ( transition.second == q ) + res.insert ( std::make_pair ( transition.first, q ) ); + } + + return res; + } + + /** + * \returns transitions from state @p q + */ + ext::map < ext::pair < common::ranked_symbol < SymbolType, RankType >, ext::vector < StateType > >, StateType > getTransitionsFromState ( const StateType & q ) const { + ext::map < ext::pair < common::ranked_symbol < SymbolType, RankType >, ext::vector < StateType > >, StateType > res; + + for ( const auto & transition : getTransitions ( ) ) { + if ( std::find ( transition.first.second.begin ( ), transition.first.second.end ( ), q ) != transition.first.second.end ( ) ) + res.insert ( transition ); + } + + return res; + } + /** * \brief Computes number of transitions in the automaton * diff --git a/alib2data/src/automaton/TA/NFTA.h b/alib2data/src/automaton/TA/NFTA.h index 8855b1ae37..8803547885 100644 --- a/alib2data/src/automaton/TA/NFTA.h +++ b/alib2data/src/automaton/TA/NFTA.h @@ -318,6 +318,33 @@ public: return std::move ( transitions ); } + /** + * \returns transitions to state @p q + */ + ext::map < ext::pair < common::ranked_symbol < SymbolType, RankType >, ext::vector < StateType > >, ext::set < StateType > > getTransitionsToState ( const StateType & q ) const { + ext::map < ext::pair < common::ranked_symbol < SymbolType, RankType >, ext::vector < StateType > >, ext::set < StateType > > res; + + for ( const auto & transition : getTransitions ( ) ) + if ( std::find ( transition.second.begin ( ), transition.second.end ( ), q ) != transition.second.end ( ) ) + res [ transition.first ].insert ( q ); + + return res; + } + + /** + * \returns transitions from state @p q + */ + ext::map < ext::pair < common::ranked_symbol < SymbolType, RankType >, ext::vector < StateType > >, ext::set < StateType > > getTransitionsFromState ( const StateType & q ) const { + ext::map < ext::pair < common::ranked_symbol < SymbolType, RankType >, ext::vector < StateType > >, ext::set < StateType > > res; + + for ( const auto & transition : getTransitions ( ) ) { + if ( std::find ( transition.first.second.begin ( ), transition.first.second.end ( ), q ) != transition.first.second.end ( ) ) + res.insert ( transition ); + } + + return res; + } + /** * \brief Determines whether the automaton is deterministic. * -- GitLab