diff --git a/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp b/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp index 37d1d49b8b771cffc328ed53575a7ccf6df7ce6e..064c765b37c2bc512610767e84039ebe6eecb984 100644 --- a/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp +++ b/alib2algo/src/automaton/properties/AllEpsilonClosure.cpp @@ -7,126 +7,15 @@ #include "AllEpsilonClosure.h" -#include <automaton/FSM/ExtendedNFA.h> -#include <automaton/FSM/CompactNFA.h> -#include <automaton/FSM/EpsilonNFA.h> -#include <automaton/FSM/MultiInitialStateNFA.h> -#include <automaton/FSM/NFA.h> -#include <automaton/FSM/DFA.h> - -#include <set> -#include <map> -#include <deque> -#include <iostream> - -#include "../../regexp/properties/RegExpEpsilon.h" - - namespace automaton { namespace properties { -std::map<DefaultStateType, std::set<DefaultStateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::EpsilonNFA < > & fsm) { - std::deque<std::map<DefaultStateType, std::set<DefaultStateType>>> Qi; - - Qi.push_back({}); - for(const DefaultStateType& state : fsm.getStates()) - Qi.at(0)[state].insert(state); - - int i = 1; - while(true) { - Qi.push_back( Qi.at( i - 1 ) ); - - for( const std::pair<const DefaultStateType, std::set<DefaultStateType>> & p : Qi.at( i - 1 ) ) - for(const DefaultStateType& pclosure : p.second ) - for(const auto& transition : fsm.getEpsilonTransitionsFromState(pclosure)) { - Qi.at( i )[p.first].insert(transition.second.begin(), transition.second.end()); - } - - if( Qi.at( i ) == Qi.at( i - 1 ) ) - break; - - i = i + 1; - }; - - return Qi.at(i); -} - auto AllEpsilonClosureEpsilonNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::EpsilonNFA < > >(AllEpsilonClosure::allEpsilonClosure); - -std::map<DefaultStateType, std::set<DefaultStateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::MultiInitialStateNFA < > & fsm) { - std::map<DefaultStateType, std::set<DefaultStateType>> closure; - for(const DefaultStateType& state : fsm.getStates()) - closure[state].insert(state); - return closure; -} - auto AllEpsilonClosureMultiInitialStateNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::MultiInitialStateNFA < > >(AllEpsilonClosure::allEpsilonClosure); - -std::map<DefaultStateType, std::set<DefaultStateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::NFA < > & fsm) { - std::map<DefaultStateType, std::set<DefaultStateType>> closure; - for(const DefaultStateType& state : fsm.getStates()) - closure[state].insert(state); - return closure; -} - auto AllEpsilonClosureNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::NFA < > >(AllEpsilonClosure::allEpsilonClosure); - -std::map<DefaultStateType, std::set<DefaultStateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::DFA < > & fsm) { - std::map<DefaultStateType, std::set<DefaultStateType>> closure; - for(const DefaultStateType& state : fsm.getStates()) - closure[state].insert(state); - return closure; -} - auto AllEpsilonClosureDFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::DFA<>>(AllEpsilonClosure::allEpsilonClosure); - -std::map<DefaultStateType, std::set<DefaultStateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::ExtendedNFA < > & fsm) { - std::map<DefaultStateType, std::set<DefaultStateType>> res; - std::map<DefaultStateType, std::set<DefaultStateType>> step; - - for(const std::pair<const std::pair<DefaultStateType, regexp::UnboundedRegExpStructure < DefaultSymbolType > >, std::set<DefaultStateType> >& transition : fsm.getTransitions() ) - if( regexp::properties::RegExpEpsilon::languageContainsEpsilon( transition.first.second ) ) - step[transition.first.first].insert(transition.second.begin(), transition.second.end()); - - for(const DefaultStateType& state : fsm.getStates()) - step[state].insert(state); - - do { - res = step; - - for(const std::pair<const DefaultStateType, std::set<DefaultStateType>>& item : res) - for(const DefaultStateType& to : item.second) - step[item.first].insert(res[to].begin(), res[to].end()); - } while(res != step); - - return res; -} - auto AllEpsilonClosureExtendedNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::ExtendedNFA < > >(AllEpsilonClosure::allEpsilonClosure); - -std::map<DefaultStateType, std::set<DefaultStateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::CompactNFA < > & fsm) { - std::map<DefaultStateType, std::set<DefaultStateType>> res; - std::map<DefaultStateType, std::set<DefaultStateType>> step; - - for(const std::pair<const std::pair<DefaultStateType, std::vector < DefaultSymbolType > >, std::set<DefaultStateType> >& transition : fsm.getTransitions() ) - if( transition.first.second.size() == 0 ) - step[transition.first.first].insert(transition.second.begin(), transition.second.end()); - - for(const DefaultStateType& state : fsm.getStates()) - step[state].insert(state); - - do { - res = step; - - for(const std::pair<const DefaultStateType, std::set<DefaultStateType>>& item : res) - for(const DefaultStateType& to : item.second) - step[item.first].insert(res[to].begin(), res[to].end()); - } while(res != step); - - return res; -} - auto AllEpsilonClosureCompactNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::CompactNFA < > >(AllEpsilonClosure::allEpsilonClosure); std::map<DefaultStateType, std::set<DefaultStateType>> AllEpsilonClosure::allEpsilonClosure(const Automaton& automaton) { diff --git a/alib2algo/src/automaton/properties/AllEpsilonClosure.h b/alib2algo/src/automaton/properties/AllEpsilonClosure.h index e6e2cebce0784360244adcc5f63e4069bb2c5bb6..4a4f8a3fd720400613466e39e8863c4d5661fe90 100644 --- a/alib2algo/src/automaton/properties/AllEpsilonClosure.h +++ b/alib2algo/src/automaton/properties/AllEpsilonClosure.h @@ -11,10 +11,20 @@ #include <core/multipleDispatch.hpp> #include <set> #include <map> +#include <deque> +#include <iostream> #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/MultiInitialStateNFA.h> +#include <automaton/FSM/NFA.h> +#include <automaton/FSM/DFA.h> + +#include "../../regexp/properties/RegExpEpsilon.h" namespace automaton { @@ -27,14 +37,117 @@ public: /** * Computes allEpsilon closure of a state in allEpsilon nonfree automaton */ - static std::map<DefaultStateType, std::set<DefaultStateType>> allEpsilonClosure( const automaton::EpsilonNFA < > & fsm); - static std::map<DefaultStateType, std::set<DefaultStateType>> allEpsilonClosure( const automaton::MultiInitialStateNFA < > & fsm); - static std::map<DefaultStateType, std::set<DefaultStateType>> allEpsilonClosure( const automaton::NFA < > & fsm); - static std::map<DefaultStateType, std::set<DefaultStateType>> allEpsilonClosure( const automaton::DFA < > & fsm); - static std::map<DefaultStateType, std::set<DefaultStateType>> allEpsilonClosure( const automaton::ExtendedNFA < > & fsm); - static std::map<DefaultStateType, std::set<DefaultStateType>> allEpsilonClosure( const automaton::CompactNFA < > & fsm); + template < class SymbolType, class EpsilonType, class StateType > + static std::map<StateType, std::set<StateType>> allEpsilonClosure( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm); + template < class SymbolType, class StateType > + static std::map<StateType, std::set<StateType>> allEpsilonClosure( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm); + template < class SymbolType, class StateType > + static std::map<StateType, std::set<StateType>> allEpsilonClosure( const automaton::NFA < SymbolType, StateType > & fsm); + template < class SymbolType, class StateType > + static std::map<StateType, std::set<StateType>> allEpsilonClosure( const automaton::DFA < SymbolType, StateType > & fsm); + template < class SymbolType, class StateType > + static std::map<StateType, std::set<StateType>> allEpsilonClosure( const automaton::ExtendedNFA < SymbolType, StateType > & fsm); + template < class SymbolType, class StateType > + static std::map<StateType, std::set<StateType>> allEpsilonClosure( const automaton::CompactNFA < SymbolType, StateType > & fsm); }; +template < class SymbolType, class EpsilonType, class StateType > +std::map<StateType, std::set<StateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm) { + std::deque<std::map<StateType, std::set<StateType>>> Qi; + + Qi.push_back({}); + for(const StateType& state : fsm.getStates()) + Qi.at(0)[state].insert(state); + + int i = 1; + while(true) { + Qi.push_back( Qi.at( i - 1 ) ); + + for( const std::pair<const StateType, std::set<StateType>> & p : Qi.at( i - 1 ) ) + for(const StateType& pclosure : p.second ) + for(const auto& transition : fsm.getEpsilonTransitionsFromState(pclosure)) { + Qi.at( i )[p.first].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 > +std::map<StateType, std::set<StateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm) { + std::map<StateType, std::set<StateType>> closure; + for(const StateType& state : fsm.getStates()) + closure[state].insert(state); + return closure; +} + +template < class SymbolType, class StateType > +std::map<StateType, std::set<StateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::NFA < SymbolType, StateType > & fsm) { + std::map<StateType, std::set<StateType>> closure; + for(const StateType& state : fsm.getStates()) + closure[state].insert(state); + return closure; +} + +template < class SymbolType, class StateType > +std::map<StateType, std::set<StateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::DFA < SymbolType, StateType > & fsm) { + std::map<StateType, std::set<StateType>> closure; + for(const StateType& state : fsm.getStates()) + closure[state].insert(state); + return closure; +} + +template < class SymbolType, class StateType > +std::map<StateType, std::set<StateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::ExtendedNFA < SymbolType, StateType > & fsm) { + std::map<StateType, std::set<StateType>> res; + std::map<StateType, std::set<StateType>> step; + + for(const std::pair<const std::pair<StateType, regexp::UnboundedRegExpStructure < SymbolType > >, std::set<StateType> >& transition : fsm.getTransitions() ) + if( regexp::properties::RegExpEpsilon::languageContainsEpsilon( transition.first.second ) ) + step[transition.first.first].insert(transition.second.begin(), transition.second.end()); + + for(const StateType& state : fsm.getStates()) + step[state].insert(state); + + do { + res = step; + + for(const std::pair<const StateType, std::set<StateType>>& item : res) + for(const StateType& to : item.second) + step[item.first].insert(res[to].begin(), res[to].end()); + } while(res != step); + + return res; +} + +template < class SymbolType, class StateType > +std::map<StateType, std::set<StateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::CompactNFA < SymbolType, StateType > & fsm) { + std::map<StateType, std::set<StateType>> res; + std::map<StateType, std::set<StateType>> step; + + for(const std::pair<const std::pair<StateType, std::vector < SymbolType > >, std::set<StateType> >& transition : fsm.getTransitions() ) + if( transition.first.second.size() == 0 ) + step[transition.first.first].insert(transition.second.begin(), transition.second.end()); + + for(const StateType& state : fsm.getStates()) + step[state].insert(state); + + do { + res = step; + + for(const std::pair<const StateType, std::set<StateType>>& item : res) + for(const StateType& to : item.second) + step[item.first].insert(res[to].begin(), res[to].end()); + } while(res != step); + + return res; +} + } /* namespace properties */ } /* namespace automaton */ diff --git a/alib2algo/src/automaton/properties/EpsilonClosure.cpp b/alib2algo/src/automaton/properties/EpsilonClosure.cpp index b47a135fe16e3d43841d726f896f2c2e93526efc..6061c6c0adcb24d76d6d888ad69e01a123b5b46c 100644 --- a/alib2algo/src/automaton/properties/EpsilonClosure.cpp +++ b/alib2algo/src/automaton/properties/EpsilonClosure.cpp @@ -7,142 +7,15 @@ #include "EpsilonClosure.h" -#include <automaton/FSM/ExtendedNFA.h> -#include <automaton/FSM/CompactNFA.h> -#include <automaton/FSM/EpsilonNFA.h> -#include <automaton/FSM/MultiInitialStateNFA.h> -#include <automaton/FSM/NFA.h> -#include <automaton/FSM/DFA.h> - -#include <set> -#include <map> -#include <queue> - -#include "../../regexp/properties/RegExpEpsilon.h" - namespace automaton { namespace properties { -std::set<DefaultStateType> EpsilonClosure::epsilonClosure( const automaton::EpsilonNFA < > & fsm, const DefaultStateType & q ) { - if(! fsm.getStates().count(q) ) throw exception::CommonException("State is not in the automaton"); - - std::set<DefaultStateType> closure; - std::queue<DefaultStateType> queue; - std::map<DefaultStateType, bool> visited; - - for( const auto & p : fsm.getStates( ) ) - visited[ p ] = false; - - queue.push( q ); - while( ! queue.empty( ) ) - { - DefaultStateType p = queue.front( ); - queue.pop( ); - visited[ p ] = true; - closure.insert( p ); - - auto tos = fsm.getTransitions( ).find(std::make_pair(p, std::variant<string::Epsilon < >, DefaultSymbolType>(string::Epsilon < >::EPSILON) ) ); - if(tos == fsm.getTransitions().end()) continue; - - for( const auto & to : tos->second ) - if( visited [ to ] == false ) - queue.push( to ); - } - - return closure; -} - auto EpsilonClosureEpsilonNFA = EpsilonClosure::RegistratorWrapper<std::set<DefaultStateType>, automaton::EpsilonNFA < > >(EpsilonClosure::epsilonClosure); - -std::set<DefaultStateType> EpsilonClosure::epsilonClosure( const automaton::MultiInitialStateNFA < > & fsm, const DefaultStateType & q ) { - if(! fsm.getStates().count(q) ) throw exception::CommonException("State is not in the automaton"); - - std::set<DefaultStateType> closure; - closure.insert(q); - return closure; -} - auto EpsilonClosureMultiInitialStateNFA = EpsilonClosure::RegistratorWrapper<std::set<DefaultStateType>, automaton::MultiInitialStateNFA < > >(EpsilonClosure::epsilonClosure); - -std::set<DefaultStateType> EpsilonClosure::epsilonClosure( const automaton::NFA < > & fsm, const DefaultStateType & q ) { - if(! fsm.getStates().count(q) ) throw exception::CommonException("State is not in the automaton"); - - std::set<DefaultStateType> closure; - closure.insert(q); - return closure; -} - auto EpsilonClosureNFA = EpsilonClosure::RegistratorWrapper<std::set<DefaultStateType>, automaton::NFA < > >(EpsilonClosure::epsilonClosure); - -std::set<DefaultStateType> EpsilonClosure::epsilonClosure( const automaton::DFA < > & fsm, const DefaultStateType & q ) { - if(! fsm.getStates().count(q) ) throw exception::CommonException("State is not in the automaton"); - - std::set<DefaultStateType> closure; - closure.insert(q); - return closure; -} - auto EpsilonClosureDFA = EpsilonClosure::RegistratorWrapper<std::set<DefaultStateType>, automaton::DFA<>>(EpsilonClosure::epsilonClosure); - -std::set<DefaultStateType> EpsilonClosure::epsilonClosure( const automaton::ExtendedNFA < > & fsm, const DefaultStateType & q ) { - if(! fsm.getStates().count(q) ) throw exception::CommonException("State is not in the automaton"); - - std::set<DefaultStateType> closure; - std::queue<DefaultStateType> queue; - std::map<DefaultStateType, bool> visited; - - for( const auto & p : fsm.getStates( ) ) - visited[ p ] = false; - - queue.push( q ); - while( ! queue.empty( ) ) - { - DefaultStateType p = queue.front( ); - queue.pop( ); - visited[ p ] = true; - closure.insert( p ); - - for( const auto & transition : fsm.getTransitionsFromState( p ) ) - if( regexp::properties::RegExpEpsilon::languageContainsEpsilon( transition.first.second ) ) - for (const auto & to : transition.second ) - if( visited [ to ] == false ) - queue.push( to ); - } - - return closure; -} - auto EpsilonClosureExtendedNFA = EpsilonClosure::RegistratorWrapper<std::set<DefaultStateType>, automaton::ExtendedNFA < > >(EpsilonClosure::epsilonClosure); - -std::set<DefaultStateType> EpsilonClosure::epsilonClosure( const automaton::CompactNFA < > & fsm, const DefaultStateType & q ) { - if(! fsm.getStates().count(q) ) throw exception::CommonException("State is not in the automaton"); - - std::set<DefaultStateType> closure; - std::queue<DefaultStateType> queue; - std::map<DefaultStateType, bool> visited; - - for( const auto & p : fsm.getStates( ) ) - visited[ p ] = false; - - queue.push( q ); - while( ! queue.empty( ) ) - { - DefaultStateType p = queue.front( ); - queue.pop( ); - visited[ p ] = true; - closure.insert( p ); - - 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 ); - } - - return closure; -} - auto EpsilonClosureCompactNFA = EpsilonClosure::RegistratorWrapper<std::set<DefaultStateType>, automaton::CompactNFA < > >(EpsilonClosure::epsilonClosure); std::set<DefaultStateType> EpsilonClosure::epsilonClosure(const Automaton& automaton, const DefaultStateType& q) { diff --git a/alib2algo/src/automaton/properties/EpsilonClosure.h b/alib2algo/src/automaton/properties/EpsilonClosure.h index 3b01ecc5d75572b9a8a940743d3e86286c6ee4ed..b1998622163667d65879d8e0a9b9f488ae8cc010 100644 --- a/alib2algo/src/automaton/properties/EpsilonClosure.h +++ b/alib2algo/src/automaton/properties/EpsilonClosure.h @@ -11,11 +11,21 @@ #include <core/multipleDispatch.hpp> #include <algorithm> #include <deque> +#include <queue> #include <set> +#include <map> #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/MultiInitialStateNFA.h> +#include <automaton/FSM/NFA.h> +#include <automaton/FSM/DFA.h> + +#include "../../regexp/properties/RegExpEpsilon.h" namespace automaton { @@ -28,14 +38,132 @@ public: /** * Computes epsilon closure of a state in epsilon nonfree automaton */ - static std::set<DefaultStateType> epsilonClosure( const automaton::EpsilonNFA < > & fsm, const DefaultStateType & state ); - static std::set<DefaultStateType> epsilonClosure( const automaton::MultiInitialStateNFA < > & fsm, const DefaultStateType & state ); - static std::set<DefaultStateType> epsilonClosure( const automaton::NFA < > & fsm, const DefaultStateType & state ); - static std::set<DefaultStateType> epsilonClosure( const automaton::DFA < > & fsm, const DefaultStateType & state ); - static std::set<DefaultStateType> epsilonClosure( const automaton::ExtendedNFA < > & fsm, const DefaultStateType & state ); - static std::set<DefaultStateType> epsilonClosure( const automaton::CompactNFA < > & fsm, const DefaultStateType & state ); + template < class SymbolType, class EpsilonType, class StateType > + static std::set<StateType> epsilonClosure( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm, const StateType & state ); + template < class SymbolType, class StateType > + static std::set<StateType> epsilonClosure( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm, const StateType & state ); + template < class SymbolType, class StateType > + static std::set<StateType> epsilonClosure( const automaton::NFA < SymbolType, StateType > & fsm, const StateType & state ); + template < class SymbolType, class StateType > + static std::set<StateType> epsilonClosure( const automaton::DFA < SymbolType, StateType > & fsm, const StateType & state ); + template < class SymbolType, class StateType > + static std::set<StateType> epsilonClosure( const automaton::ExtendedNFA < SymbolType, StateType > & fsm, const StateType & state ); + template < class SymbolType, class StateType > + static std::set<StateType> epsilonClosure( const automaton::CompactNFA < SymbolType, StateType > & fsm, const StateType & state ); }; +template < class SymbolType, class EpsilonType, class StateType > +std::set<StateType> EpsilonClosure::epsilonClosure( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm, const StateType & q ) { + if(! fsm.getStates().count(q) ) throw exception::CommonException("State is not in the automaton"); + + std::set<StateType> closure; + std::queue<StateType> queue; + std::map<StateType, bool> visited; + + for( const auto & p : fsm.getStates( ) ) + visited[ p ] = false; + + queue.push( q ); + while( ! queue.empty( ) ) { + StateType p = queue.front( ); + queue.pop( ); + visited[ p ] = true; + closure.insert( p ); + + auto tos = fsm.getTransitions( ).find(std::make_pair ( p, std::variant < EpsilonType, SymbolType >::template from < EpsilonType > ( ) ) ); + if(tos == fsm.getTransitions().end()) continue; + + for( const auto & to : tos->second ) + if( visited [ to ] == false ) + queue.push( to ); + } + + return closure; +} + +template < class SymbolType, class StateType > +std::set<StateType> EpsilonClosure::epsilonClosure( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm, const StateType & q ) { + if(! fsm.getStates().count(q) ) throw exception::CommonException("State is not in the automaton"); + + std::set<StateType> closure; + closure.insert(q); + return closure; +} + +template < class SymbolType, class StateType > +std::set<StateType> EpsilonClosure::epsilonClosure( const automaton::NFA < SymbolType, StateType > & fsm, const StateType & q ) { + if(! fsm.getStates().count(q) ) throw exception::CommonException("State is not in the automaton"); + + std::set<StateType> closure; + closure.insert(q); + return closure; +} + +template < class SymbolType, class StateType > +std::set<StateType> EpsilonClosure::epsilonClosure( const automaton::DFA < SymbolType, StateType > & fsm, const StateType & q ) { + if(! fsm.getStates().count(q) ) throw exception::CommonException("State is not in the automaton"); + + std::set<StateType> closure; + closure.insert(q); + return closure; +} + +template < class SymbolType, class StateType > +std::set<StateType> EpsilonClosure::epsilonClosure( const automaton::ExtendedNFA < SymbolType, StateType > & fsm, const StateType & q ) { + if(! fsm.getStates().count(q) ) throw exception::CommonException("State is not in the automaton"); + + std::set<StateType> closure; + std::queue<StateType> queue; + std::map<StateType, bool> visited; + + for( const auto & p : fsm.getStates( ) ) + visited[ p ] = false; + + queue.push( q ); + while( ! queue.empty( ) ) { + StateType p = queue.front( ); + queue.pop( ); + visited[ p ] = true; + closure.insert( p ); + + for( const auto & transition : fsm.getTransitionsFromState( p ) ) + if( regexp::properties::RegExpEpsilon::languageContainsEpsilon( transition.first.second ) ) + for (const auto & to : transition.second ) + if( visited [ to ] == false ) + queue.push( to ); + } + + return closure; +} + +template < class SymbolType, class StateType > +std::set<StateType> EpsilonClosure::epsilonClosure( const automaton::CompactNFA < SymbolType, StateType > & fsm, const StateType & q ) { + if(! fsm.getStates().count(q) ) throw exception::CommonException("State is not in the automaton"); + + std::set<StateType> closure; + std::queue<StateType> queue; + std::map<StateType, bool> visited; + + for( const auto & p : fsm.getStates( ) ) + visited[ p ] = false; + + queue.push( q ); + while( ! queue.empty( ) ) { + StateType p = queue.front( ); + queue.pop( ); + visited[ p ] = true; + closure.insert( p ); + + 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 ); + } + + return closure; +} + } /* namespace properties */ } /* namespace automaton */ diff --git a/alib2algo/src/automaton/properties/ReachableStates.cpp b/alib2algo/src/automaton/properties/ReachableStates.cpp index 833ca31c7fb14d869ee7fe4d3d75209c97748dd5..5130b8555c29c9457e8e04b5b8bb4b019a56c5f0 100644 --- a/alib2algo/src/automaton/properties/ReachableStates.cpp +++ b/alib2algo/src/automaton/properties/ReachableStates.cpp @@ -7,16 +7,6 @@ #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 { @@ -25,91 +15,11 @@ std::set<DefaultStateType> ReachableStates::reachableStates(const Automaton& aut return dispatch(automaton.getData()); } -template<class T> -std::set<DefaultStateType> ReachableStates::reachableStates( const T & fsm ) { - // 1a - std::deque<std::set<DefaultStateType>> Qi; - Qi.push_back( std::set<DefaultStateType>( ) ); - Qi.at( 0 ) = {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 ); -} - 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); - -template<> -std::set<DefaultStateType> ReachableStates::reachableStates( const automaton::MultiInitialStateNFA < > & fsm ) { - // 1a - std::deque<std::set<DefaultStateType>> Qi; - Qi.push_back( std::set<DefaultStateType>( ) ); - Qi.at( 0 ) = fsm.getInitialStates( ); - - 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 ); -} - auto ReachableStatesMultiInitialStateNFA = ReachableStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::MultiInitialStateNFA < > >(ReachableStates::reachableStates); - -template<> -std::set<DefaultStateType> ReachableStates::reachableStates( const automaton::DFA < > & fsm ) { - // 1a - std::deque<std::set<DefaultStateType>> Qi; - Qi.push_back( std::set<DefaultStateType>( ) ); - 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 ); -} - auto ReachableStatesDFA = ReachableStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::DFA<>>(ReachableStates::reachableStates); } /* namespace properties */ diff --git a/alib2algo/src/automaton/properties/ReachableStates.h b/alib2algo/src/automaton/properties/ReachableStates.h index 8e25478e3bc709d3f7e484b0daba5ce81987495a..dacbfbc378f4302cff02571f14abdf74a337ea2d 100644 --- a/alib2algo/src/automaton/properties/ReachableStates.h +++ b/alib2algo/src/automaton/properties/ReachableStates.h @@ -12,10 +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 { @@ -28,10 +35,92 @@ public: /** * Removes dead states from FSM. Melichar 2.29 */ - template<class T> - static std::set<DefaultStateType> 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 ) { + // 1a + std::deque<std::set<StateType>> Qi; + Qi.push_back( std::set<StateType>( ) ); + Qi.at( 0 ) = {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 > +std::set<StateType> ReachableStates::reachableStates( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm ) { + // 1a + std::deque<std::set<StateType>> Qi; + Qi.push_back( std::set<StateType>( ) ); + Qi.at( 0 ) = fsm.getInitialStates( ); + + 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 > +std::set<StateType> ReachableStates::reachableStates( const automaton::DFA < SymbolType, StateType > & fsm ) { + // 1a + std::deque<std::set<StateType>> Qi; + Qi.push_back( std::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 ); +} + } /* namespace properties */ } /* namespace automaton */ diff --git a/alib2algo/src/automaton/properties/UsefullStates.cpp b/alib2algo/src/automaton/properties/UsefullStates.cpp index 05fb5eacc37ba9d6b9a8323616bacb8e459fa516..353e9c23a5d9de4814bbb20ae69919aef985ac7a 100644 --- a/alib2algo/src/automaton/properties/UsefullStates.cpp +++ b/alib2algo/src/automaton/properties/UsefullStates.cpp @@ -7,16 +7,6 @@ #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 { @@ -25,60 +15,11 @@ std::set<DefaultStateType> UsefullStates::usefullStates(const Automaton& automat return dispatch(automaton.getData()); } -template<class T> -std::set<DefaultStateType> UsefullStates::usefullStates( const T & fsm ) { - // 1a - std::deque<std::set<DefaultStateType>> Qi; - Qi.push_back( std::set<DefaultStateType>( ) ); - Qi.at( 0 ) = fsm.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 : fsm.getTransitionsToState( p ) ) - Qi.at( i ).insert( t.first.first ); - - if( Qi.at( i ) == Qi.at( i - 1 ) ) - break; - - i = i + 1; - } - return Qi.at( i ); -} - 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); - -template<> -std::set<DefaultStateType> UsefullStates::usefullStates( const automaton::DFA < > & fsm ) { - // 1a - std::deque<std::set<DefaultStateType>> Qi; - Qi.push_back( std::set<DefaultStateType>( ) ); - Qi.at( 0 ) = fsm.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 : fsm.getTransitionsToState( p ) ) - Qi.at( i ).insert( t.first.first ); - - if( Qi.at( i ) == Qi.at( i - 1 ) ) - break; - - i = i + 1; - } - return Qi.at( i ); -} - auto UsefullStatesDFA = UsefullStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::DFA<>>(UsefullStates::usefullStates); } /* namespace properties */ diff --git a/alib2algo/src/automaton/properties/UsefullStates.h b/alib2algo/src/automaton/properties/UsefullStates.h index 6bdf867f3c9b55c6f18de3c47c5e7a5643b7e616..936fecd2001b272c080bfd29e304f8b09013bdb6 100644 --- a/alib2algo/src/automaton/properties/UsefullStates.h +++ b/alib2algo/src/automaton/properties/UsefullStates.h @@ -12,10 +12,16 @@ #include <algorithm> #include <deque> #include <set> +#include <map> #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 { @@ -28,10 +34,60 @@ public: /** * Removes dead states from FSM. Melichar 2.32 */ - template<class T> - static std::set<DefaultStateType> 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 ) { + // 1a + std::deque<std::set<StateType>> Qi; + Qi.push_back( std::set<StateType>( ) ); + Qi.at( 0 ) = fsm.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 : fsm.getTransitionsToState( p ) ) + Qi.at( i ).insert( t.first.first ); + + if( Qi.at( i ) == Qi.at( i - 1 ) ) + break; + + i = i + 1; + } + return Qi.at( i ); +} + +template < class SymbolType, class StateType > +std::set<StateType> UsefullStates::usefullStates( const automaton::DFA < SymbolType, StateType > & fsm ) { + // 1a + std::deque<std::set<StateType>> Qi; + Qi.push_back( std::set<StateType>( ) ); + Qi.at( 0 ) = fsm.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 : fsm.getTransitionsToState( p ) ) + Qi.at( i ).insert( t.first.first ); + + if( Qi.at( i ) == Qi.at( i - 1 ) ) + break; + + i = i + 1; + } + return Qi.at( i ); +} + } /* namespace properties */ } /* namespace automaton */