From 50c88b572cbe436df77051600f40492e43bade66 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Tue, 20 Dec 2016 17:11:13 +0100 Subject: [PATCH] template AllEpsilonClosure --- .../efficient/AllEpsilonClosure.cpp | 146 +--------------- .../properties/efficient/AllEpsilonClosure.h | 158 +++++++++++++++++- 2 files changed, 156 insertions(+), 148 deletions(-) diff --git a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp index ac6e066589..0966da9435 100644 --- a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp +++ b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp @@ -7,152 +7,20 @@ #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 <iostream> - -#include <regexp/properties/RegExpEpsilon.h> - namespace automaton { namespace properties { namespace efficient { -void process(const std::map<label::Label, std::set<label::Label>>& epsilonTransitions, const label::Label * state, std::map<label::Label, std::set<label::Label>>& closures, std::set<label::Label>& visited, std::set<label::Label>& nonvisited) { - if(visited.count(*state)) return; - - state = &*visited.insert(*state).first; - nonvisited.erase(*state); - - auto tos = epsilonTransitions.find(*state); - if(tos == epsilonTransitions.end()) return; - - for(const label::Label& to : tos->second) { - process(epsilonTransitions, &to, closures, visited, nonvisited); - closures[*state].insert(closures[to].begin(), closures[to].end()); - } -} - -std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::EpsilonNFA < > & fsm) { - std::map<label::Label, std::set<label::Label>> res; - - for(const label::Label& state : fsm.getStates()) - res[state].insert(state); - - std::set<label::Label> visited; - std::set<label::Label> nonvisited = fsm.getStates(); - - std::map<label::Label, std::set<label::Label>> epsilonTransitions = fsm.getEpsilonTransitions(); - - while(nonvisited.size()) { - process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited); - } - - // to correctly handle epsilon loops (swap visited and nonvisited) - - while(visited.size()) { - process(epsilonTransitions, &*visited.begin(), res, nonvisited, visited); - } - - return res; -} - -auto AllEpsilonClosureEpsilonNFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::EpsilonNFA < > >(AllEpsilonClosure::allEpsilonClosure); - -std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::MultiInitialStateNFA < > & fsm) { - std::map<label::Label, std::set<label::Label>> closure; - for(const label::Label& state : fsm.getStates()) - closure[state].insert(state); - return closure; -} - -auto AllEpsilonClosureMultiInitialStateNFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::MultiInitialStateNFA < >>(AllEpsilonClosure::allEpsilonClosure); - -std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::NFA < > & fsm) { - std::map<label::Label, std::set<label::Label>> closure; - for(const label::Label& state : fsm.getStates()) - closure[state].insert(state); - return closure; -} - -auto AllEpsilonClosureNFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::NFA < > >(AllEpsilonClosure::allEpsilonClosure); - -std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::DFA < > & fsm) { - std::map<label::Label, std::set<label::Label>> closure; - for(const label::Label& state : fsm.getStates()) - closure[state].insert(state); - return closure; -} - -auto AllEpsilonClosureDFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::DFA<>>(AllEpsilonClosure::allEpsilonClosure); - -std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::ExtendedNFA < > & fsm) { - std::map<label::Label, std::set<label::Label>> res; - - for(const label::Label& state : fsm.getStates()) - res[state].insert(state); - - std::set<label::Label> visited; - std::set<label::Label> nonvisited = fsm.getStates(); - - std::map<label::Label, std::set<label::Label>> epsilonTransitions; - for(const std::pair<const std::pair<label::Label, regexp::UnboundedRegExpStructure < alphabet::Symbol > >, std::set<label::Label> >& transition : fsm.getTransitions() ) - if( regexp::properties::RegExpEpsilon::languageContainsEpsilon( transition.first.second ) ) - epsilonTransitions[transition.first.first].insert(transition.second.begin(), transition.second.end()); - - while(nonvisited.size()) { - process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited); - } - - // to correctly handle epsilon loops (swap visited and nonvisited) - - while(visited.size()) { - process(epsilonTransitions, &*visited.begin(), res, nonvisited, visited); - } - - return res; -} - -auto AllEpsilonClosureExtendedNFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::ExtendedNFA < > >(AllEpsilonClosure::allEpsilonClosure); - -std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::CompactNFA < > & fsm) { - std::map<label::Label, std::set<label::Label>> res; - - for(const label::Label& state : fsm.getStates()) - res[state].insert(state); - - std::set<label::Label> visited; - std::set<label::Label> nonvisited = fsm.getStates(); - - std::map<label::Label, std::set<label::Label>> epsilonTransitions; - for(const std::pair<const std::pair<label::Label, std::vector < alphabet::Symbol > >, std::set<label::Label> >& transition : fsm.getTransitions() ) - if( transition.first.second.size() == 0 ) - epsilonTransitions[transition.first.first].insert(transition.second.begin(), transition.second.end()); - - while(nonvisited.size()) { - process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited); - } - - // to correctly handle epsilon loops (swap visited and nonvisited) - - while(visited.size()) { - process(epsilonTransitions, &*visited.begin(), res, nonvisited, visited); - } - - return res; -} - -auto AllEpsilonClosureCompactNFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::CompactNFA < > >(AllEpsilonClosure::allEpsilonClosure); +auto AllEpsilonClosureEpsilonNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::EpsilonNFA < > >(AllEpsilonClosure::allEpsilonClosure); +auto AllEpsilonClosureMultiInitialStateNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::MultiInitialStateNFA < >>(AllEpsilonClosure::allEpsilonClosure); +auto AllEpsilonClosureNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::NFA < > >(AllEpsilonClosure::allEpsilonClosure); +auto AllEpsilonClosureDFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::DFA<>>(AllEpsilonClosure::allEpsilonClosure); +auto AllEpsilonClosureExtendedNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::ExtendedNFA < > >(AllEpsilonClosure::allEpsilonClosure); +auto AllEpsilonClosureCompactNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::CompactNFA < > >(AllEpsilonClosure::allEpsilonClosure); -std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure(const Automaton& automaton) { +std::map<DefaultStateType, std::set<DefaultStateType>> AllEpsilonClosure::allEpsilonClosure(const Automaton& automaton) { return dispatch(automaton.getData()); } diff --git a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h index a0e51e4af1..6168f8ea0f 100644 --- a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h +++ b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h @@ -15,7 +15,18 @@ #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 <set> +#include <map> +#include <iostream> + +#include <regexp/properties/RegExpEpsilon.h> namespace automaton { @@ -23,21 +34,150 @@ namespace properties { namespace efficient { -class AllEpsilonClosure : public std::SingleDispatch<AllEpsilonClosure, std::map<label::Label, std::set<label::Label>>, const automaton::AutomatonBase &> { +class AllEpsilonClosure : public std::SingleDispatch<AllEpsilonClosure, std::map<DefaultStateType, std::set<DefaultStateType>>, const automaton::AutomatonBase &> { + template < class StateType > + static void process(const std::map<StateType, std::set<StateType>>& epsilonTransitions, const StateType * state, std::map<StateType, std::set<StateType>>& closures, std::set<StateType>& visited, std::set<StateType>& nonvisited); public: - static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::Automaton & automaton); + static std::map<DefaultStateType, std::set<DefaultStateType>> allEpsilonClosure( const automaton::Automaton & automaton); /** * Computes allEpsilon closure of a state in allEpsilon nonfree automaton */ - static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::EpsilonNFA < > & fsm); - static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::MultiInitialStateNFA < > & fsm); - static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::NFA < > & fsm); - static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::DFA < > & fsm); - static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::ExtendedNFA < > & fsm); - static std::map<label::Label, std::set<label::Label>> 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 StateType > +void AllEpsilonClosure::process(const std::map<StateType, std::set<StateType>>& epsilonTransitions, const StateType * state, std::map<StateType, std::set<StateType>>& closures, std::set<StateType>& visited, std::set<StateType>& nonvisited) { + if(visited.count(*state)) return; + + state = &*visited.insert(*state).first; + nonvisited.erase(*state); + + auto tos = epsilonTransitions.find(*state); + if(tos == epsilonTransitions.end()) return; + + for(const StateType& to : tos->second) { + process(epsilonTransitions, &to, closures, visited, nonvisited); + closures[*state].insert(closures[to].begin(), closures[to].end()); + } +} + +template < class SymbolType, class EpsilonType, class StateType > +std::map<StateType, std::set<StateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm) { + std::map<StateType, std::set<StateType>> res; + + for(const StateType& state : fsm.getStates()) + res[state].insert(state); + + std::set<StateType> visited; + std::set<StateType> nonvisited = fsm.getStates(); + + std::map<StateType, std::set<StateType>> epsilonTransitions = fsm.getEpsilonTransitions(); + + while(nonvisited.size()) { + process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited); + } + + // to correctly handle epsilon loops (swap visited and nonvisited) + + while(visited.size()) { + process(epsilonTransitions, &*visited.begin(), res, nonvisited, visited); + } + + return res; +} + +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; + + for(const StateType& state : fsm.getStates()) + res[state].insert(state); + + std::set<StateType> visited; + std::set<StateType> nonvisited = fsm.getStates(); + + std::map<StateType, std::set<StateType>> epsilonTransitions; + 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 ) ) + epsilonTransitions[transition.first.first].insert(transition.second.begin(), transition.second.end()); + + while(nonvisited.size()) { + process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited); + } + + // to correctly handle epsilon loops (swap visited and nonvisited) + + while(visited.size()) { + process(epsilonTransitions, &*visited.begin(), res, nonvisited, visited); + } + + 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; + + for(const StateType& state : fsm.getStates()) + res[state].insert(state); + + std::set<StateType> visited; + std::set<StateType> nonvisited = fsm.getStates(); + + std::map<StateType, std::set<StateType>> epsilonTransitions; + for(const std::pair<const std::pair<StateType, std::vector < SymbolType > >, std::set<StateType> >& transition : fsm.getTransitions() ) + if( transition.first.second.size() == 0 ) + epsilonTransitions[transition.first.first].insert(transition.second.begin(), transition.second.end()); + + while(nonvisited.size()) { + process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited); + } + + // to correctly handle epsilon loops (swap visited and nonvisited) + + while(visited.size()) { + process(epsilonTransitions, &*visited.begin(), res, nonvisited, visited); + } + + return res; +} + } /* namespace efficient */ } /* namespace properties */ -- GitLab