From 7136b31e0034bec729d18893f9b290084245a1c4 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Wed, 21 Dec 2016 11:02:55 +0100 Subject: [PATCH] finish templating elgo algorithms --- .../properties/efficient/ReachableStates.cpp | 92 ++----------------- .../properties/efficient/ReachableStates.h | 86 ++++++++++++++++- .../properties/efficient/UsefullStates.cpp | 70 ++------------ .../properties/efficient/UsefullStates.h | 63 ++++++++++++- .../automaton/simplify/efficient/trimTest.cpp | 22 ++--- 5 files changed, 164 insertions(+), 169 deletions(-) diff --git a/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp b/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp index 9fb30fc6b1..b634efafda 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 006b6c1fa3..6113170771 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 4804bd174c..5c5db127c9 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 4067b441d9..8710c3934f 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 8efff3d38d..316d2878b8 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); } -- GitLab