diff --git a/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp b/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp index 9fb30fc6b1162477e14f1721cef55e74a51cf7ac..b634efafda090605dbc29ed78163419a0cf32638 100644 --- a/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp +++ b/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp @@ -7,100 +7,22 @@ #include "ReachableStates.h" -#include <automaton/FSM/ExtendedNFA.h> -#include <automaton/FSM/CompactNFA.h> -#include <automaton/FSM/EpsilonNFA.h> -#include <automaton/FSM/NFA.h> -#include <automaton/FSM/DFA.h> - -#include <set> -#include <map> -#include <queue> - namespace automaton { namespace properties { namespace efficient { -std::set<label::Label> ReachableStates::reachableStates(const Automaton& automaton) { +std::set<DefaultStateType> ReachableStates::reachableStates(const Automaton& automaton) { return dispatch(automaton.getData()); } -template<class T> -std::set<label::Label> ReachableStates::reachableStates( const T & fsm ) { - std::map<label::Label, std::set<label::Label>> transitions; - for(const auto& transition : fsm.getTransitions()) - transitions[transition.first.first].insert(transition.second.begin(), transition.second.end()); - - std::deque<label::Label> queue { fsm.getInitialState( ) }; - std::set<label::Label> visited { fsm.getInitialState( ) }; - - while( !queue.empty() ) { - const std::set<label::Label>& to = transitions[queue.front()]; - queue.pop_front(); - - for(const label::Label& process : to) - if(visited.insert(process).second) { - queue.push_back(std::move(const_cast<label::Label&>(process))); - } - } - - return visited; -} - -auto ReachableStatesEpsilonNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::EpsilonNFA < > >(ReachableStates::reachableStates); -auto ReachableStatesNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::NFA < > >(ReachableStates::reachableStates); -auto ReachableStatesCompactNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::CompactNFA < > >(ReachableStates::reachableStates); -auto ReachableStatesExtendedNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::ExtendedNFA < > >(ReachableStates::reachableStates); - -template<> -std::set<label::Label> ReachableStates::reachableStates( const automaton::MultiInitialStateNFA < > & fsm ) { - std::map<label::Label, std::set<label::Label>> transitions; - for(const auto& transition : fsm.getTransitions()) - transitions[transition.first.first].insert(transition.second.begin(), transition.second.end()); - - std::deque<label::Label> queue ( fsm.getInitialStates( ).begin(), fsm.getInitialStates().end() ); - std::set<label::Label> visited = fsm.getInitialStates( ); - - while( !queue.empty() ) { - const std::set<label::Label>& to = transitions[queue.front()]; - queue.pop_front(); - - for(const label::Label& process : to) - if(visited.insert(process).second) { - queue.push_back(std::move(const_cast<label::Label&>(process))); - } - } - - return visited; -} - -auto ReachableStatesMultiInitialStateNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::MultiInitialStateNFA < >>(ReachableStates::reachableStates); - -template<> -std::set<label::Label> ReachableStates::reachableStates( const automaton::DFA < > & fsm ) { - std::map<label::Label, std::set<label::Label>> transitions; - for(const auto& transition : fsm.getTransitions()) - transitions[transition.first.first].insert(transition.second); - - std::deque<label::Label> queue { fsm.getInitialState( ) }; - std::set<label::Label> visited { fsm.getInitialState( ) }; - - while( !queue.empty() ) { - const std::set<label::Label>& to = transitions[queue.front()]; - queue.pop_front(); - - for(const label::Label& process : to) - if(visited.insert(process).second) { - queue.push_back(std::move(const_cast<label::Label&>(process))); - } - } - - return visited; -} - -auto ReachableStatesDFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::DFA<>>(ReachableStates::reachableStates); +auto ReachableStatesEpsilonNFA = ReachableStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::EpsilonNFA < > >(ReachableStates::reachableStates); +auto ReachableStatesNFA = ReachableStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::NFA < > >(ReachableStates::reachableStates); +auto ReachableStatesCompactNFA = ReachableStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::CompactNFA < > >(ReachableStates::reachableStates); +auto ReachableStatesExtendedNFA = ReachableStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::ExtendedNFA < > >(ReachableStates::reachableStates); +auto ReachableStatesMultiInitialStateNFA = ReachableStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::MultiInitialStateNFA < >>(ReachableStates::reachableStates); +auto ReachableStatesDFA = ReachableStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::DFA < > >(ReachableStates::reachableStates); } /* namespace efficient */ diff --git a/alib2elgo/src/automaton/properties/efficient/ReachableStates.h b/alib2elgo/src/automaton/properties/efficient/ReachableStates.h index 006b6c1fa37dcadc83e5e3068bde2069429bab5c..61131707714ab2768502454ef44acc05886e6a22 100644 --- a/alib2elgo/src/automaton/properties/efficient/ReachableStates.h +++ b/alib2elgo/src/automaton/properties/efficient/ReachableStates.h @@ -12,11 +12,17 @@ #include <algorithm> #include <deque> #include <set> +#include <map> +#include <queue> #include <automaton/Automaton.h> #include <automaton/AutomatonFeatures.h> -#include <label/Label.h> +#include <automaton/FSM/ExtendedNFA.h> +#include <automaton/FSM/CompactNFA.h> +#include <automaton/FSM/EpsilonNFA.h> +#include <automaton/FSM/NFA.h> +#include <automaton/FSM/DFA.h> namespace automaton { @@ -24,17 +30,87 @@ namespace properties { namespace efficient { -class ReachableStates : public std::SingleDispatch<ReachableStates, std::set<label::Label>, const automaton::AutomatonBase &> { +class ReachableStates : public std::SingleDispatch<ReachableStates, std::set<DefaultStateType>, const automaton::AutomatonBase &> { public: - static std::set<label::Label> reachableStates( const automaton::Automaton & automaton ); + static std::set<DefaultStateType> reachableStates( const automaton::Automaton & automaton ); /** * Removes dead states from FSM. Melichar 2.29 */ - template<class T> - static std::set<label::Label> reachableStates( const T & fsm ); + template < class T, class SymbolType = typename automaton::SymbolTypeOfAutomaton < T >, class StateType = typename automaton::StateTypeOfAutomaton < T > > + static std::set<StateType> reachableStates( const T & fsm ); + template < class SymbolType, class StateType > + static std::set<StateType> reachableStates( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm ); + template < class SymbolType, class StateType > + static std::set<StateType> reachableStates( const automaton::DFA < SymbolType, StateType > & fsm ); }; +template < class T, class SymbolType, class StateType > +std::set<StateType> ReachableStates::reachableStates( const T & fsm ) { + std::map<StateType, std::set<StateType>> transitions; + for(const auto& transition : fsm.getTransitions()) + transitions[transition.first.first].insert(transition.second.begin(), transition.second.end()); + + std::deque<StateType> queue { fsm.getInitialState( ) }; + std::set<StateType> visited { fsm.getInitialState( ) }; + + while( !queue.empty() ) { + const std::set<StateType>& to = transitions[queue.front()]; + queue.pop_front(); + + for(const StateType& process : to) + if(visited.insert(process).second) { + queue.push_back(std::move(const_cast<StateType&>(process))); + } + } + + return visited; +} + +template < class SymbolType, class StateType > +std::set<StateType> ReachableStates::reachableStates( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm ) { + std::map<StateType, std::set<StateType>> transitions; + for(const auto& transition : fsm.getTransitions()) + transitions[transition.first.first].insert(transition.second.begin(), transition.second.end()); + + std::deque<StateType> queue ( fsm.getInitialStates( ).begin(), fsm.getInitialStates().end() ); + std::set<StateType> visited = fsm.getInitialStates( ); + + while( !queue.empty() ) { + const std::set<StateType>& to = transitions[queue.front()]; + queue.pop_front(); + + for(const StateType& process : to) + if(visited.insert(process).second) { + queue.push_back(std::move(const_cast<StateType&>(process))); + } + } + + return visited; +} + +template < class SymbolType, class StateType > +std::set<StateType> ReachableStates::reachableStates( const automaton::DFA < SymbolType, StateType > & fsm ) { + std::map<StateType, std::set<StateType>> transitions; + for(const auto& transition : fsm.getTransitions()) + transitions[transition.first.first].insert(transition.second); + + std::deque<StateType> queue { fsm.getInitialState( ) }; + std::set<StateType> visited { fsm.getInitialState( ) }; + + while( !queue.empty() ) { + const std::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/UsefullStates.cpp b/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp index 4804bd174cc2d53352c87ae2c1eb4fff47ea8bad..5c5db127c91e6f3ad5b98d5ae5224531a99cb83b 100644 --- a/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp +++ b/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp @@ -7,78 +7,22 @@ #include "UsefullStates.h" -#include <automaton/FSM/ExtendedNFA.h> -#include <automaton/FSM/CompactNFA.h> -#include <automaton/FSM/EpsilonNFA.h> -#include <automaton/FSM/NFA.h> -#include <automaton/FSM/DFA.h> - -#include <set> -#include <map> -#include <queue> - namespace automaton { namespace properties { namespace efficient { -std::set<label::Label> UsefullStates::usefullStates(const Automaton& automaton) { +std::set<DefaultStateType> UsefullStates::usefullStates(const Automaton& automaton) { return dispatch(automaton.getData()); } -template<class T> -std::set<label::Label> UsefullStates::usefullStates( const T & fsm ) { - std::map<label::Label, std::set<label::Label>> reversedTransitions; - for(const auto& transition : fsm.getTransitions()) - for(const label::Label& to : transition.second) - reversedTransitions[to].insert(transition.first.first); - - std::deque<label::Label> queue ( fsm.getFinalStates( ).begin(), fsm.getFinalStates().end() ); - std::set<label::Label> visited = fsm.getFinalStates( ); - - while( !queue.empty() ) { - const std::set<label::Label>& to = reversedTransitions[queue.front()]; - queue.pop_front(); - - for(const label::Label& process : to) - if(visited.insert(process).second) { - queue.push_back(std::move(const_cast<label::Label&>(process))); - } - } - - return visited; -} - -auto UsefullStatesEpsilonNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::EpsilonNFA < > >(UsefullStates::usefullStates); -auto UsefullStatesNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::NFA < > >(UsefullStates::usefullStates); -auto UsefullStatesCompactNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::CompactNFA < > >(UsefullStates::usefullStates); -auto UsefullStatesExtendedNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::ExtendedNFA < > >(UsefullStates::usefullStates); -auto UsefullStatesMultiInitialStateNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::MultiInitialStateNFA < >>(UsefullStates::usefullStates); - -template<> -std::set<label::Label> UsefullStates::usefullStates( const automaton::DFA < > & fsm ) { - std::map<label::Label, std::set<label::Label>> reversedTransitions; - for(const auto& transition : fsm.getTransitions()) - reversedTransitions[transition.second].insert(transition.first.first); - - std::deque<label::Label> queue ( fsm.getFinalStates( ).begin(), fsm.getFinalStates().end() ); - std::set<label::Label> visited = fsm.getFinalStates( ); - - while( !queue.empty() ) { - const std::set<label::Label>& to = reversedTransitions[queue.front()]; - queue.pop_front(); - - for(const label::Label& process : to) - if(visited.insert(process).second) { - queue.push_back(std::move(const_cast<label::Label&>(process))); - } - } - - return visited; -} - -auto UsefullStatesDFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::DFA<>>(UsefullStates::usefullStates); +auto UsefullStatesEpsilonNFA = UsefullStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::EpsilonNFA < > >(UsefullStates::usefullStates); +auto UsefullStatesNFA = UsefullStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::NFA < > >(UsefullStates::usefullStates); +auto UsefullStatesCompactNFA = UsefullStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::CompactNFA < > >(UsefullStates::usefullStates); +auto UsefullStatesExtendedNFA = UsefullStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::ExtendedNFA < > >(UsefullStates::usefullStates); +auto UsefullStatesMultiInitialStateNFA = UsefullStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::MultiInitialStateNFA < >>(UsefullStates::usefullStates); +auto UsefullStatesDFA = UsefullStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::DFA < > >(UsefullStates::usefullStates); } /* namespace efficient */ diff --git a/alib2elgo/src/automaton/properties/efficient/UsefullStates.h b/alib2elgo/src/automaton/properties/efficient/UsefullStates.h index 4067b441d95361162f36657e2d3b11b549af255f..8710c3934f7a861515acffc5b0ebb13844f924cc 100644 --- a/alib2elgo/src/automaton/properties/efficient/UsefullStates.h +++ b/alib2elgo/src/automaton/properties/efficient/UsefullStates.h @@ -12,11 +12,17 @@ #include <algorithm> #include <deque> #include <set> +#include <map> +#include <queue> #include <automaton/Automaton.h> #include <automaton/AutomatonFeatures.h> -#include <label/Label.h> +#include <automaton/FSM/ExtendedNFA.h> +#include <automaton/FSM/CompactNFA.h> +#include <automaton/FSM/EpsilonNFA.h> +#include <automaton/FSM/NFA.h> +#include <automaton/FSM/DFA.h> namespace automaton { @@ -24,17 +30,64 @@ namespace properties { namespace efficient { -class UsefullStates : public std::SingleDispatch<UsefullStates, std::set<label::Label>, const automaton::AutomatonBase &> { +class UsefullStates : public std::SingleDispatch<UsefullStates, std::set<DefaultStateType>, const automaton::AutomatonBase &> { public: - static std::set<label::Label> usefullStates( const automaton::Automaton & automaton ); + static std::set<DefaultStateType> usefullStates( const automaton::Automaton & automaton ); /** * Removes dead states from FSM. Melichar 2.32 */ - template<class T> - static std::set<label::Label> usefullStates( const T & fsm ); + template < class T, class SymbolType = typename automaton::SymbolTypeOfAutomaton < T >, class StateType = typename automaton::StateTypeOfAutomaton < T > > + static std::set<StateType> usefullStates( const T & fsm ); + template < class SymbolType, class StateType > + static std::set<StateType> usefullStates( const automaton::DFA < SymbolType, StateType > & fsm ); }; +template < class T, class SymbolType, class StateType > +std::set<StateType> UsefullStates::usefullStates( const T & fsm ) { + std::map<StateType, std::set<StateType>> reversedTransitions; + for(const auto& transition : fsm.getTransitions()) + for(const StateType& to : transition.second) + reversedTransitions[to].insert(transition.first.first); + + std::deque<StateType> queue ( fsm.getFinalStates( ).begin(), fsm.getFinalStates().end() ); + std::set<StateType> visited = fsm.getFinalStates( ); + + while( !queue.empty() ) { + const std::set<StateType>& to = reversedTransitions[queue.front()]; + queue.pop_front(); + + for(const StateType& process : to) + if(visited.insert(process).second) { + queue.push_back(std::move(const_cast<StateType&>(process))); + } + } + + return visited; +} + +template < class SymbolType, class StateType > +std::set<StateType> UsefullStates::usefullStates( const automaton::DFA < SymbolType, StateType > & fsm ) { + std::map<StateType, std::set<StateType>> reversedTransitions; + for(const auto& transition : fsm.getTransitions()) + reversedTransitions[transition.second].insert(transition.first.first); + + std::deque<StateType> queue ( fsm.getFinalStates( ).begin(), fsm.getFinalStates().end() ); + std::set<StateType> visited = fsm.getFinalStates( ); + + while( !queue.empty() ) { + const std::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/test-src/automaton/simplify/efficient/trimTest.cpp b/alib2elgo/test-src/automaton/simplify/efficient/trimTest.cpp index 8efff3d38dbd1475ceacf2de8794d9082ce14156..316d2878b8fe386aa27e5f91f4f550f1aa8df1d0 100644 --- a/alib2elgo/test-src/automaton/simplify/efficient/trimTest.cpp +++ b/alib2elgo/test-src/automaton/simplify/efficient/trimTest.cpp @@ -17,21 +17,21 @@ void trimTest::tearDown() { } void trimTest::testTrimAutomaton() { - automaton::DFA<> automaton(label::Label(1)); + automaton::DFA < > automaton(DefaultStateType(1)); - automaton.addState(label::Label(1)); - automaton.addState(label::Label(2)); - automaton.addState(label::Label(3)); - automaton.addInputSymbol(alphabet::Symbol("a")); - automaton.addInputSymbol(alphabet::Symbol("b")); + automaton.addState(DefaultStateType(1)); + automaton.addState(DefaultStateType(2)); + automaton.addState(DefaultStateType(3)); + automaton.addInputSymbol(DefaultSymbolType("a")); + automaton.addInputSymbol(DefaultSymbolType("b")); - automaton.addTransition(label::Label(1), alphabet::Symbol("a"), label::Label(2)); - automaton.addTransition(label::Label(2), alphabet::Symbol("b"), label::Label(1)); - automaton.addTransition(label::Label(3), alphabet::Symbol("b"), label::Label(1)); + automaton.addTransition(DefaultStateType(1), DefaultSymbolType("a"), DefaultStateType(2)); + automaton.addTransition(DefaultStateType(2), DefaultSymbolType("b"), DefaultStateType(1)); + automaton.addTransition(DefaultStateType(3), DefaultSymbolType("b"), DefaultStateType(1)); - automaton.addFinalState(label::Label(1)); + automaton.addFinalState(DefaultStateType(1)); - automaton::DFA<> trimed = automaton::simplify::Trim::trim(automaton); + automaton::DFA < > trimed = automaton::simplify::Trim::trim(automaton); CPPUNIT_ASSERT(trimed.getStates().size() == 2); }