From 4420f89a5e23c155d9662b78e46a0707d6aa7bb8 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Fri, 17 Oct 2014 22:12:40 +0200 Subject: [PATCH] unify StateElimination --- aconversions2/src/ConversionHandler.cpp | 48 +--- aconversions2/src/ConversionHandler.h | 7 +- .../conversions/fa2re/StateElimination.cpp | 174 ++++++++++++ ...minationUnbounded.h => StateElimination.h} | 19 +- .../fa2re/formal/StateEliminationFormal.cpp | 268 ------------------ .../fa2re/formal/StateEliminationFormal.h | 67 ----- .../unbounded/StateEliminationUnbounded.cpp | 247 ---------------- alib2algo/src/regexp/RegExpAlternate.cpp | 10 +- alib2algo/src/regexp/RegExpAlternate.h | 6 +- 9 files changed, 198 insertions(+), 648 deletions(-) create mode 100644 alib2algo/src/conversions/fa2re/StateElimination.cpp rename alib2algo/src/conversions/fa2re/{unbounded/StateEliminationUnbounded.h => StateElimination.h} (70%) delete mode 100644 alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.cpp delete mode 100644 alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.h delete mode 100644 alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.cpp diff --git a/aconversions2/src/ConversionHandler.cpp b/aconversions2/src/ConversionHandler.cpp index dec0494d0b..afda692fa1 100644 --- a/aconversions2/src/ConversionHandler.cpp +++ b/aconversions2/src/ConversionHandler.cpp @@ -7,8 +7,7 @@ #include "ConversionHandler.h" -#include "conversions/fa2re/unbounded/StateEliminationUnbounded.h" -#include "conversions/fa2re/formal/StateEliminationFormal.h" +#include "conversions/fa2re/StateElimination.h" #include "conversions/fa2re/Algebraic.h" #include "conversions/re2fa/GlushkovNFA.h" @@ -98,37 +97,7 @@ void ConversionHandler::convertRG( void ) // ---------------------------------------------------------------------------- -void ConversionHandler::convertFSMtoRE(void) -{ - switch( m_target ) - { - case REGULAR_EXPRESSION_FORMAL: - convertFSMtoREF(); - break; - default: - convertFSMtoREU(); - break; - } -} - -void ConversionHandler::convertFSMtoREF(void) -{ - const automaton::Automaton automaton = alib::DataFactory::fromTokens<automaton::Automaton>(m_tokens); - - switch( m_algorithm ) - { - case BRZOZOWSKI_ALGEBRAIC: - break; - case STATE_ELIMINATION: - default: { - alib::DataFactory::toStdout(conversions::fa2re::StateEliminationFormal::convert(automaton)); - break; - } - } - -} - -void ConversionHandler::convertFSMtoREU( void ) +void ConversionHandler::convertFSMtoRE( void ) { const automaton::Automaton automaton = alib::DataFactory::fromTokens<automaton::Automaton>(m_tokens); @@ -151,7 +120,7 @@ void ConversionHandler::convertFSMtoREU( void ) } case STATE_ELIMINATION: default: { - alib::DataFactory::toStdout(conversions::fa2re::StateEliminationUnbounded::convert(automaton)); + alib::DataFactory::toStdout(conversions::fa2re::StateElimination::convert(automaton)); break; } } @@ -317,9 +286,7 @@ ConversionHandler::TFormalism ConversionHandler::parseFormalismFromString( const return FINITE_AUTOMATON; if( target == "re" || target == "regexp" || target == "regex" ) - return REGULAR_EXPRESSION_UNBOUNDED; - if (target == "formalre" || target == "formalregexp" || target == "formalregex") - return REGULAR_EXPRESSION_FORMAL; + return REGULAR_EXPRESSION; if( target == "rrg" || target == "rg" || target == "grammar" ) return RIGHT_REGULAR_GRAMMAR; @@ -337,11 +304,8 @@ ConversionHandler::TFormalism ConversionHandler::parseFormalismFromTokens( void if( xmlMark == "automaton" || xmlMark == "NFA" || xmlMark == "DFA" ) return FINITE_AUTOMATON; - if( xmlMark == "regexp" || xmlMark == "unboundedRegexp" ) - return REGULAR_EXPRESSION_UNBOUNDED; - - if(xmlMark == "formalRegExp") - return REGULAR_EXPRESSION_FORMAL; + if( xmlMark == "regexp" || xmlMark == "unboundedRegexp" || xmlMark == "formalRegExp") + return REGULAR_EXPRESSION; if( xmlMark == "RightRG" ) return RIGHT_REGULAR_GRAMMAR; diff --git a/aconversions2/src/ConversionHandler.h b/aconversions2/src/ConversionHandler.h index 998978f9a1..6ef4568382 100644 --- a/aconversions2/src/ConversionHandler.h +++ b/aconversions2/src/ConversionHandler.h @@ -66,15 +66,14 @@ public: LEFT_LINEAR_GRAMMAR, RIGHT_LINEAR_GRAMMAR, - REGULAR_EXPRESSION_UNBOUNDED, - REGULAR_EXPRESSION_FORMAL, + REGULAR_EXPRESSION, UNKNOWN, }; #define isGrammar(x) ( (x) == REGULAR_GRAMMAR || (x) == LEFT_REGULAR_GRAMMAR || (x) == RIGHT_REGULAR_GRAMMAR \ || (x) == LINEAR_GRAMMAR || (x) == LEFT_LINEAR_GRAMMAR || (x) == RIGHT_LINEAR_GRAMMAR ) - #define isRegExp(x) ( (x) == REGULAR_EXPRESSION_FORMAL || (x) == REGULAR_EXPRESSION_UNBOUNDED ) + #define isRegExp(x) ( (x) == REGULAR_EXPRESSION ) ConversionHandler( std::list<sax::Token> & tokens, const std::string & target, const std::string & algorithm, std::ostream & out ); void convert( void ); @@ -86,8 +85,6 @@ private: void convertFSM( void ); void convertFSMtoRE( void ); - void convertFSMtoREF( void ); - void convertFSMtoREU( void ); void convertFSMtoRG( void ); void convertFSMtoLRG( void ); void convertFSMtoRRG( void ); diff --git a/alib2algo/src/conversions/fa2re/StateElimination.cpp b/alib2algo/src/conversions/fa2re/StateElimination.cpp new file mode 100644 index 0000000000..2c933a2f6c --- /dev/null +++ b/alib2algo/src/conversions/fa2re/StateElimination.cpp @@ -0,0 +1,174 @@ +/* + * StateEliminationUnbounded.cpp + * + * Created on: 9. 2. 2014 + * Author: Tomas Pecka + */ + +#include "StateElimination.h" + +#include <regexp/unbounded/UnboundedRegExp.h> +#include <exception/AlibException.h> + +#include "../../regexp/RegExpOptimize.h" +#include "../../regexp/RegExpAlternate.h" +#include "../../regexp/RegExpConcatenate.h" +#include "../../regexp/RegExpIterate.h" + +namespace conversions +{ + +namespace fa2re +{ + +regexp::RegExp StateElimination::convert(const automaton::Automaton& automaton) +{ + regexp::RegExp* out = NULL; + automaton.getData().Accept((void*) &out, StateElimination::STATE_ELIMINATION); + regexp::RegExp res = std::move(*out); + delete out; + return res; +} + +template<class T> +regexp::RegExp StateElimination::convert(const T& automaton) +{ + if(automaton.getFinalStates().size() == 0) + return regexp::RegExp(regexp::UnboundedRegExp(regexp::UnboundedRegExpEmpty())); + + // steps 1 + 2 + automaton::ExtendedNFA extendedAutomaton(automaton); + extendExtendedNFA(extendedAutomaton); + + // step 3 - Exterminate! + // select all states that are neither final nor initial + std::set<automaton::State> statesToEliminate = extendedAutomaton.getStates(); + statesToEliminate.erase(extendedAutomaton.getInitialState()); + statesToEliminate.erase(*extendedAutomaton.getFinalStates().begin()); + + for(const auto& state : statesToEliminate) + extendedAutomaton = eliminateState(extendedAutomaton, state); + + // step 4 + regexp::RegExpOptimize opt; + + return opt.optimize(regexp::RegExpConcatenate::concatenate( + transition(extendedAutomaton, extendedAutomaton.getInitialState(), *extendedAutomaton.getFinalStates().begin()), + regexp::RegExpIterate::iterate(transition(extendedAutomaton, *extendedAutomaton.getFinalStates().begin(), *extendedAutomaton.getFinalStates().begin())))); +} + + +void StateElimination::Visit(void* data, const automaton::EpsilonNFA& automaton) const +{ + regexp::RegExp* & out = *((regexp::RegExp**) data); + out = new regexp::RegExp(convert(automaton)); +} + +void StateElimination::Visit(void* data, const automaton::MultiInitialStateNFA& automaton) const +{ + regexp::RegExp* & out = *((regexp::RegExp**) data); + out = new regexp::RegExp(convert(automaton)); +} + +void StateElimination::Visit(void* data, const automaton::NFA& automaton) const +{ + regexp::RegExp* & out = *((regexp::RegExp**) data); + out = new regexp::RegExp(convert(automaton)); +} + +void StateElimination::Visit(void* data, const automaton::DFA& automaton) const +{ + regexp::RegExp* & out = *((regexp::RegExp**) data); + out = new regexp::RegExp(convert(automaton)); +} + +void StateElimination::Visit(void* data, const automaton::ExtendedNFA& automaton) const +{ + regexp::RegExp* & out = *((regexp::RegExp**) data); + out = new regexp::RegExp(convert(automaton)); +} + +void StateElimination::Visit(void* data, const automaton::CompactNFA& automaton) const +{ + regexp::RegExp* & out = *((regexp::RegExp**) data); + out = new regexp::RegExp(convert(automaton)); +} + +automaton::ExtendedNFA StateElimination::eliminateState(const automaton::ExtendedNFA& extendedAutomaton, const automaton::State& q) +{ + automaton::ExtendedNFA newAutomaton(extendedAutomaton.getInitialState()); // sure that q is neither initial nor final (follows from step 2 - extending ExtendedNFA) + newAutomaton.setStates(extendedAutomaton.getStates()); + newAutomaton.removeState(q); // preserve all states but q (the one to eliminate) + newAutomaton.setInputSymbols(extendedAutomaton.getInputAlphabet()); + newAutomaton.setFinalStates(extendedAutomaton.getFinalStates()); + + regexp::RegExpOptimize opt; + + for(const auto& p: newAutomaton.getStates()) + { + for(const auto& r : newAutomaton.getStates()) + { + regexp::RegExp concat = transition(extendedAutomaton, p, q); + concat = regexp::RegExpConcatenate::concatenate(concat, regexp::RegExpIterate::iterate(transition(extendedAutomaton, q, q))); + concat = regexp::RegExpConcatenate::concatenate(concat, transition(extendedAutomaton, q, r)); + + regexp::RegExp alt = regexp::RegExpAlternate::alternate(concat, transition(extendedAutomaton, p, r)); + + newAutomaton.addTransition(p, opt.optimize(alt), r); + } + } + + return newAutomaton; +} + +const regexp::RegExp StateElimination::transition(const automaton::ExtendedNFA& automaton, const automaton::State& from, const automaton::State& to) +{ + regexp::RegExpOptimize opt; + regexp::RegExp ret(regexp::UnboundedRegExp(regexp::UnboundedRegExpEmpty { })); + + for(const auto& transition: automaton.getTransitionsFromState(from)) + if(transition.second.count(to) > 0) + ret = regexp::RegExpAlternate::alternate(ret, transition.first.second); + + return opt.optimize(ret); +} + +void StateElimination::extendExtendedNFA(automaton::ExtendedNFA& automaton) +{ + const automaton::State& initState = automaton.getInitialState(); + if(automaton.getFinalStates().count(initState) > 0 || automaton.getTransitionsToState(initState).size() > 0 ) + { + const automaton::State q0 = automaton::createUniqueState(initState, automaton.getStates()); + automaton.addState(q0); + + regexp::UnboundedRegExp regexp; + regexp.setRegExp(regexp::UnboundedRegExpEpsilon()); + automaton.addTransition(q0, regexp::RegExp{regexp}, initState); + + automaton.setInitialState(q0); + } + + if(automaton.getFinalStates().size() > 1) + { + const automaton::State f = automaton::createUniqueState(automaton::State("f"), automaton.getStates()); + automaton.addState(f); + + const std::set<automaton::State> automatonFinalStates = automaton.getFinalStates(); + for(const auto &state : automatonFinalStates) + { + regexp::UnboundedRegExp regexp; + regexp.setRegExp(regexp::UnboundedRegExpEpsilon()); + automaton.addTransition(state, regexp::RegExp{regexp}, f); + + automaton.removeFinalState(state); + } + + automaton.addFinalState(f); + } +} + +const StateElimination StateElimination::STATE_ELIMINATION; + +} /* namespace fa2re */ + +} /* namespace conversions */ diff --git a/alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.h b/alib2algo/src/conversions/fa2re/StateElimination.h similarity index 70% rename from alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.h rename to alib2algo/src/conversions/fa2re/StateElimination.h index 481994b421..ab54785825 100644 --- a/alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.h +++ b/alib2algo/src/conversions/fa2re/StateElimination.h @@ -1,12 +1,12 @@ /* - * StateEliminationUnbounded.h + * StateElimination.h * * Created on: 9. 2. 2014 * Author: Tomas Pecka */ -#ifndef STATEELIMINATIONUNBOUNDED_H_ -#define STATEELIMINATIONUNBOUNDED_H_ +#ifndef STATEELIMINATION_H_ +#define STATEELIMINATION_H_ #include <regexp/RegExp.h> #include <regexp/unbounded/UnboundedRegExpElements.h> @@ -28,7 +28,7 @@ namespace fa2re * Converts FSM to RE using State Elimination algorithm. * Source: Melichar 2.118 */ -class StateEliminationUnbounded : public automaton::VisitableConstFSMBase +class StateElimination : public automaton::VisitableConstFSMBase { public: /** @@ -39,7 +39,7 @@ public: static regexp::RegExp convert(const automaton::Automaton& automaton); template<class T> - static regexp::UnboundedRegExp convert(const T& automaton); + static regexp::RegExp convert(const T& automaton); private: void Visit(void*, const automaton::EpsilonNFA& automaton) const; @@ -49,20 +49,17 @@ private: void Visit(void*, const automaton::ExtendedNFA& automaton) const; void Visit(void*, const automaton::CompactNFA& automaton) const; - template<class T> - static automaton::ExtendedNFA constructExtendedNFA(const T& automaton); - static void extendExtendedNFA(automaton::ExtendedNFA& automaton); - static const regexp::UnboundedRegExpElement* transition(const automaton::ExtendedNFA& automaton, const automaton::State& from, const automaton::State& to); + static const regexp::RegExp transition(const automaton::ExtendedNFA& automaton, const automaton::State& from, const automaton::State& to); static automaton::ExtendedNFA eliminateState(const automaton::ExtendedNFA& extendedAutomaton, const automaton::State& state); - static const StateEliminationUnbounded STATE_ELIMINATION_UNBOUNDED; + static const StateElimination STATE_ELIMINATION; }; } /* namespace fa2re */ } /* namespace conversions */ -#endif /* STATEELIMINATIONUNBOUNDED_H_ */ +#endif /* STATEELIMINATION_H_ */ diff --git a/alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.cpp b/alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.cpp deleted file mode 100644 index cbc115c4fe..0000000000 --- a/alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/* - * StateEliminationFormal.cpp - * - * Created on: 9. 2. 2014 - * Author: Tomas Pecka - */ - -#include "StateEliminationFormal.h" - -#include <regexp/formal/FormalRegExp.h> -#include <exception/AlibException.h> - -#include "../../../regexp/RegExpOptimize.h" - -namespace conversions -{ - -namespace fa2re -{ - -regexp::RegExp StateEliminationFormal::convert(const automaton::Automaton& automaton) -{ - regexp::RegExp* out = NULL; - automaton.getData().Accept((void*) &out, StateEliminationFormal::STATE_ELIMINATION_FORMAL); - regexp::RegExp res = std::move(*out); - delete out; - return res; -} - -template<class T> -regexp::FormalRegExp StateEliminationFormal::convert(const T& automaton) -{ - if(automaton.getFinalStates().size() == 0) - return regexp::FormalRegExp(regexp::FormalRegExpEmpty()); - - // steps 1 + 2 - automaton::ExtendedNFA extendedAutomaton = constructExtendedNFA(automaton); - extendExtendedNFA(extendedAutomaton); - - // step 3 - Exterminate! - // select all states that are neither final nor initial - std::set<automaton::State> statesToEliminate = extendedAutomaton.getStates(); - statesToEliminate.erase(extendedAutomaton.getInitialState()); - statesToEliminate.erase(*extendedAutomaton.getFinalStates().begin()); - - for(const auto& state : statesToEliminate) - extendedAutomaton = eliminateState(extendedAutomaton, state); - - // step 4 - //regexp::RegExpOptimize opt; - - regexp::FormalRegExpConcatenation concat( - std::move(*transition(extendedAutomaton, extendedAutomaton.getInitialState(), *extendedAutomaton.getFinalStates().begin())), - regexp::FormalRegExpIteration(std::move(*transition(extendedAutomaton, *extendedAutomaton.getFinalStates().begin(), *extendedAutomaton.getFinalStates().begin()))) - ); - //return regexp::RegExp{opt.optimize(regexp::FormalRegExp(concat))}; - return regexp::FormalRegExp(concat); -} - - -void StateEliminationFormal::Visit(void* data, const automaton::EpsilonNFA& automaton) const -{ - regexp::RegExp* & out = *((regexp::RegExp**) data); - out = new regexp::RegExp(convert(automaton)); -} - -void StateEliminationFormal::Visit(void* data, const automaton::MultiInitialStateNFA& automaton) const -{ - regexp::RegExp* & out = *((regexp::RegExp**) data); - out = new regexp::RegExp(convert(automaton)); -} - -void StateEliminationFormal::Visit(void* data, const automaton::NFA& automaton) const -{ - regexp::RegExp* & out = *((regexp::RegExp**) data); - out = new regexp::RegExp(convert(automaton)); -} - -void StateEliminationFormal::Visit(void* data, const automaton::DFA& automaton) const -{ - regexp::RegExp* & out = *((regexp::RegExp**) data); - out = new regexp::RegExp(convert(automaton)); -} - -void StateEliminationFormal::Visit(void* data, const automaton::ExtendedNFA& automaton) const -{ - regexp::RegExp* & out = *((regexp::RegExp**) data); - out = new regexp::RegExp(convert(automaton)); -} - -void StateEliminationFormal::Visit(void*, const automaton::CompactNFA& ) const -{ - throw exception::AlibException("Unsupported automaton type CompactNFA"); -} - -automaton::ExtendedNFA StateEliminationFormal::eliminateState(const automaton::ExtendedNFA& extendedAutomaton, const automaton::State& q) -{ - automaton::ExtendedNFA newAutomaton(extendedAutomaton.getInitialState()); - newAutomaton.setStates(extendedAutomaton.getStates()); - newAutomaton.removeState(q); // preserve all states but q (the one to eliminate) - newAutomaton.setInputSymbols(extendedAutomaton.getInputAlphabet()); - newAutomaton.setFinalStates(extendedAutomaton.getFinalStates()); - - // regexp::RegExpOptimize opt; - - for(const auto& p: newAutomaton.getStates()) - { - for(const auto& r : newAutomaton.getStates()) - { - regexp::FormalRegExpConcatenation concat( - std::move(*transition(extendedAutomaton, p, q)), - regexp::FormalRegExpConcatenation( - regexp::FormalRegExpIteration(std::move(*transition(extendedAutomaton, q, q))), - std::move(*transition(extendedAutomaton, q, r)) - ) - ); - - regexp::FormalRegExpAlternation alt( - std::move(*transition(extendedAutomaton, p, r)), - concat - ); - - // regexp::FormalRegExp transitionRegExp(opt.optimize(regexp::FormalRegExp(alt))); - newAutomaton.addTransition(p, regexp::RegExp{regexp::FormalRegExp(alt)}, r); - } - } - - return newAutomaton; -} - -const regexp::FormalRegExpElement* StateEliminationFormal::transition(const automaton::ExtendedNFA& automaton, const automaton::State& from, const automaton::State& to) -{ - std::vector<regexp::FormalRegExpElement*> alt; - - for(const auto& transition: automaton.getTransitionsFromState(from)) - if(transition.second.count(to) > 0) - alt.push_back(static_cast<const regexp::FormalRegExp&>(transition.first.second.getData()).getRegExp().clone()); - - size_t size = alt.size(); - if(size == 0) return new regexp::FormalRegExpEmpty(); - if(size == 1) return alt.at(0); - - regexp::FormalRegExpAlternation* ret = new regexp::FormalRegExpAlternation(std::move(*alt.at(--size)), std::move(*alt.at(--size))); - while(size) - { - regexp::FormalRegExpElement* left = alt.at(--size); - regexp::FormalRegExpElement* right = ret; - - ret = new regexp::FormalRegExpAlternation(std::move(*left), std::move(*right)); - delete left; - delete right; - } - - return ret; -} - -//TODO pouzit konstruktory v alib2data -template<> -automaton::ExtendedNFA StateEliminationFormal::constructExtendedNFA(const automaton::MultiInitialStateNFA& automaton) -{ - automaton::ExtendedNFA extendedAutomaton(automaton::createUniqueState(automaton::State("q0"), automaton.getStates())); - extendedAutomaton.setStates(automaton.getStates()); - extendedAutomaton.setInputSymbols(automaton.getInputAlphabet()); - extendedAutomaton.setFinalStates(automaton.getFinalStates()); - - for(const auto& transition : automaton.getTransitions()) // pair<State, symb/eps> -> set<State> - for(const auto& to : transition.second) - extendedAutomaton.addTransition(transition.first.first, regexp::RegExp{regexp::FormalRegExp(regexp::FormalRegExpSymbol(transition.first.second))}, to); - - for(const auto& initial : automaton.getInitialStates()) - extendedAutomaton.addTransition(extendedAutomaton.getInitialState(), regexp::RegExp{regexp::UnboundedRegExp(regexp::UnboundedRegExpEmpty {})}, initial); - - return extendedAutomaton; -} - -template<> -automaton::ExtendedNFA StateEliminationFormal::constructExtendedNFA(const automaton::NFA& automaton) -{ - automaton::ExtendedNFA extendedAutomaton(automaton.getInitialState()); - extendedAutomaton.setStates(automaton.getStates()); - extendedAutomaton.setInputSymbols(automaton.getInputAlphabet()); - extendedAutomaton.setFinalStates(automaton.getFinalStates()); - - for(const auto& transition : automaton.getTransitions()) // pair<State, symb/eps> -> set<State> - for(const auto& to : transition.second) - extendedAutomaton.addTransition(transition.first.first, regexp::RegExp{regexp::FormalRegExp(regexp::FormalRegExpSymbol(transition.first.second))}, to); - - return extendedAutomaton; -} - -template<> -automaton::ExtendedNFA StateEliminationFormal::constructExtendedNFA(const automaton::DFA& automaton) -{ - automaton::ExtendedNFA extendedAutomaton(automaton.getInitialState()); - extendedAutomaton.setStates(automaton.getStates()); - extendedAutomaton.setInputSymbols(automaton.getInputAlphabet()); - extendedAutomaton.setFinalStates(automaton.getFinalStates()); - - for(const auto& transition : automaton.getTransitions()) // pair<State, symb/eps> -> set<State> - extendedAutomaton.addTransition(transition.first.first, regexp::RegExp{regexp::FormalRegExp(regexp::FormalRegExpSymbol(transition.first.second))}, transition.second); - - return extendedAutomaton; -} - -template<> -automaton::ExtendedNFA StateEliminationFormal::constructExtendedNFA(const automaton::EpsilonNFA& automaton) -{ - automaton::ExtendedNFA extendedAutomaton(automaton.getInitialState()); - extendedAutomaton.setStates(automaton.getStates()); - extendedAutomaton.setInputSymbols(automaton.getInputAlphabet()); - extendedAutomaton.setFinalStates(automaton.getFinalStates()); - - for(const auto& transition : automaton.getSymbolTransitions()) // pair<State, symb/eps> -> set<State> - for(const auto& to : transition.second) - extendedAutomaton.addTransition(transition.first.first, regexp::RegExp{regexp::FormalRegExp(regexp::FormalRegExpSymbol(transition.first.second))}, to); - - for(const auto& transition : automaton.getEpsilonTransitions()) - for(const auto& to : transition.second) - extendedAutomaton.addTransition(transition.first, regexp::RegExp{regexp::FormalRegExp(regexp::FormalRegExpEpsilon())}, to); - - return extendedAutomaton; -} - -template<> -automaton::ExtendedNFA StateEliminationFormal::constructExtendedNFA(const automaton::ExtendedNFA& automaton) -{ - return automaton; -} - -void StateEliminationFormal::extendExtendedNFA(automaton::ExtendedNFA& automaton) -{ - const automaton::State& initState = automaton.getInitialState(); - if(automaton.getFinalStates().count(initState) > 0 || automaton.getTransitionsToState(initState).size() > 0 ) - { - const automaton::State q0 = automaton::createUniqueState(initState, automaton.getStates()); - automaton.addState(q0); - - regexp::FormalRegExp regexp; - regexp.setRegExp(regexp::FormalRegExpEpsilon()); - automaton.addTransition(q0, regexp::RegExp{regexp}, initState); - - automaton.setInitialState(q0); - } - - if(automaton.getFinalStates().size() > 1) - { - const automaton::State f = automaton::createUniqueState(automaton::State("f"), automaton.getStates()); - automaton.addState(f); - - const std::set<automaton::State> automatonFinalStates = automaton.getFinalStates(); - for(const auto &state : automatonFinalStates) - { - regexp::FormalRegExp regexp; - regexp.setRegExp(regexp::FormalRegExpEpsilon()); - automaton.addTransition(state, regexp::RegExp{regexp}, f); - - automaton.removeFinalState(state); - } - - automaton.addFinalState(f); - } -} - -const StateEliminationFormal StateEliminationFormal::STATE_ELIMINATION_FORMAL; - -} /* namespace fa2re */ - -} /* namespace conversions */ diff --git a/alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.h b/alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.h deleted file mode 100644 index aeca4c7599..0000000000 --- a/alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * StateEliminationFormal.h - * - * Created on: 9. 2. 2014 - * Author: Tomas Pecka - */ - -#ifndef STATEELIMINATIONFORMAL_H_ -#define STATEELIMINATIONFORMAL_H_ - -#include <regexp/RegExp.h> -#include <regexp/formal/FormalRegExpElements.h> - -#include <automaton/Automaton.h> -#include <automaton/FSM/DFA.h> -#include <automaton/FSM/NFA.h> -#include <automaton/FSM/MultiInitialStateNFA.h> -#include <automaton/FSM/EpsilonNFA.h> -#include <automaton/FSM/ExtendedNFA.h> - -namespace conversions -{ - -namespace fa2re -{ - -/** - * Converts FSM to RE using State Elimination algorithm. - * Source: Melichar 2.118 - */ -class StateEliminationFormal : public automaton::VisitableConstFSMBase -{ -public: - /** - * Performs conversion. - * @return regular expression equivalent to source NFA. - */ - static regexp::RegExp convert(const automaton::Automaton& automaton); - - template<class T> - static regexp::FormalRegExp convert(const T& automaton); - -private: - void Visit(void*, const automaton::EpsilonNFA& automaton) const; - void Visit(void*, const automaton::MultiInitialStateNFA& automaton) const; - void Visit(void*, const automaton::NFA& automaton) const; - void Visit(void*, const automaton::DFA& automaton) const; - void Visit(void*, const automaton::ExtendedNFA& automaton) const; - void Visit(void*, const automaton::CompactNFA& automaton) const; - - template<class T> - static automaton::ExtendedNFA constructExtendedNFA(const T& automaton); - - static void extendExtendedNFA(automaton::ExtendedNFA& automaton); - - static const regexp::FormalRegExpElement* transition(const automaton::ExtendedNFA& automaton, const automaton::State& from, const automaton::State& to); - - static automaton::ExtendedNFA eliminateState(const automaton::ExtendedNFA& extendedAutomaton, const automaton::State& state); - - static const StateEliminationFormal STATE_ELIMINATION_FORMAL; -}; - -} /* namespace fa2re */ - -} /* namespace conversions */ - -#endif /* STATEELIMINATIONFORMAL_H_ */ diff --git a/alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.cpp b/alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.cpp deleted file mode 100644 index eed84f89a3..0000000000 --- a/alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - * StateEliminationUnbounded.cpp - * - * Created on: 9. 2. 2014 - * Author: Tomas Pecka - */ - -#include "StateEliminationUnbounded.h" - -#include <regexp/unbounded/UnboundedRegExp.h> -#include <exception/AlibException.h> - -#include "../../../regexp/RegExpOptimize.h" - -namespace conversions -{ - -namespace fa2re -{ - -regexp::RegExp StateEliminationUnbounded::convert(const automaton::Automaton& automaton) -{ - regexp::RegExp* out = NULL; - automaton.getData().Accept((void*) &out, StateEliminationUnbounded::STATE_ELIMINATION_UNBOUNDED); - regexp::RegExp res = std::move(*out); - delete out; - return res; -} - -template<class T> -regexp::UnboundedRegExp StateEliminationUnbounded::convert(const T& automaton) -{ - if(automaton.getFinalStates().size() == 0) - return regexp::UnboundedRegExp(regexp::UnboundedRegExpEmpty()); - - // steps 1 + 2 - automaton::ExtendedNFA extendedAutomaton = constructExtendedNFA(automaton); - extendExtendedNFA(extendedAutomaton); - - // step 3 - Exterminate! - // select all states that are neither final nor initial - std::set<automaton::State> statesToEliminate = extendedAutomaton.getStates(); - statesToEliminate.erase(extendedAutomaton.getInitialState()); - statesToEliminate.erase(*extendedAutomaton.getFinalStates().begin()); - - for(const auto& state : statesToEliminate) - extendedAutomaton = eliminateState(extendedAutomaton, state); - - // step 4 - regexp::RegExpOptimize opt; - - regexp::UnboundedRegExpConcatenation concat; - concat.appendElement(std::move(*transition(extendedAutomaton, extendedAutomaton.getInitialState(), *extendedAutomaton.getFinalStates().begin()))); - concat.appendElement(regexp::UnboundedRegExpIteration(std::move(*transition(extendedAutomaton, *extendedAutomaton.getFinalStates().begin(), *extendedAutomaton.getFinalStates().begin())))); - return opt.optimize(regexp::UnboundedRegExp(concat)); -} - - -void StateEliminationUnbounded::Visit(void* data, const automaton::EpsilonNFA& automaton) const -{ - regexp::RegExp* & out = *((regexp::RegExp**) data); - out = new regexp::RegExp(convert(automaton)); -} - -void StateEliminationUnbounded::Visit(void* data, const automaton::MultiInitialStateNFA& automaton) const -{ - regexp::RegExp* & out = *((regexp::RegExp**) data); - out = new regexp::RegExp(convert(automaton)); -} - -void StateEliminationUnbounded::Visit(void* data, const automaton::NFA& automaton) const -{ - regexp::RegExp* & out = *((regexp::RegExp**) data); - out = new regexp::RegExp(convert(automaton)); -} - -void StateEliminationUnbounded::Visit(void* data, const automaton::DFA& automaton) const -{ - regexp::RegExp* & out = *((regexp::RegExp**) data); - out = new regexp::RegExp(convert(automaton)); -} - -void StateEliminationUnbounded::Visit(void* data, const automaton::ExtendedNFA& automaton) const -{ - regexp::RegExp* & out = *((regexp::RegExp**) data); - out = new regexp::RegExp(convert(automaton)); -} - -void StateEliminationUnbounded::Visit(void*, const automaton::CompactNFA& ) const -{ - throw exception::AlibException("Unsupported automaton type CompactNFA"); -} - -automaton::ExtendedNFA StateEliminationUnbounded::eliminateState(const automaton::ExtendedNFA& extendedAutomaton, const automaton::State& q) -{ - automaton::ExtendedNFA newAutomaton(extendedAutomaton.getInitialState()); // sure that q is neither initial nor final (follows from step 2 - extending ExtendedNFA) - newAutomaton.setStates(extendedAutomaton.getStates()); - newAutomaton.removeState(q); // preserve all states but q (the one to eliminate) - newAutomaton.setInputSymbols(extendedAutomaton.getInputAlphabet()); - newAutomaton.setFinalStates(extendedAutomaton.getFinalStates()); - - regexp::RegExpOptimize opt; - - for(const auto& p: newAutomaton.getStates()) - { - for(const auto& r : newAutomaton.getStates()) - { - regexp::UnboundedRegExpConcatenation concat; - concat.appendElement(std::move(*transition(extendedAutomaton, p, q))); - concat.appendElement(regexp::UnboundedRegExpIteration(std::move(*transition(extendedAutomaton, q, q)))); - concat.appendElement(std::move(*transition(extendedAutomaton, q, r))); - - regexp::UnboundedRegExpAlternation alt; - alt.appendElement(std::move(*transition(extendedAutomaton, p, r))); - alt.appendElement(concat); - - newAutomaton.addTransition(p, regexp::RegExp{regexp::UnboundedRegExp(opt.optimize(regexp::UnboundedRegExp(alt)))}, r); - } - } - - return newAutomaton; -} - -const regexp::UnboundedRegExpElement* StateEliminationUnbounded::transition(const automaton::ExtendedNFA& automaton, const automaton::State& from, const automaton::State& to) -{ - regexp::RegExpOptimize opt; - regexp::UnboundedRegExpAlternation ret; - - for(const auto& transition: automaton.getTransitionsFromState(from)) - if(transition.second.count(to) > 0) - ret.appendElement(static_cast<const regexp::UnboundedRegExp&>(transition.first.second.getData()).getRegExp()); - - return opt.optimize(regexp::UnboundedRegExp(ret)).getRegExp().clone(); -} - -//TODO prepsat jako konstruktory v alib2data -template<> -automaton::ExtendedNFA StateEliminationUnbounded::constructExtendedNFA(const automaton::MultiInitialStateNFA& automaton) -{ - automaton::ExtendedNFA extendedAutomaton(automaton::createUniqueState(automaton::State("q0"), automaton.getStates())); - extendedAutomaton.setStates(automaton.getStates()); - extendedAutomaton.setInputSymbols(automaton.getInputAlphabet()); - extendedAutomaton.setFinalStates(automaton.getFinalStates()); - - for(const auto& transition : automaton.getTransitions()) // pair<State, symb/eps> -> set<State> - for(const auto& to : transition.second) - extendedAutomaton.addTransition(transition.first.first, regexp::RegExp{regexp::UnboundedRegExp(regexp::UnboundedRegExpSymbol(transition.first.second))}, to); - - for(const auto& initial : automaton.getInitialStates()) - extendedAutomaton.addTransition(extendedAutomaton.getInitialState(), regexp::RegExp{regexp::UnboundedRegExp(regexp::UnboundedRegExpEmpty {})}, initial); - - return extendedAutomaton; -} - -template<> -automaton::ExtendedNFA StateEliminationUnbounded::constructExtendedNFA(const automaton::NFA& automaton) -{ - automaton::ExtendedNFA extendedAutomaton(automaton.getInitialState()); - extendedAutomaton.setStates(automaton.getStates()); - extendedAutomaton.setInputSymbols(automaton.getInputAlphabet()); - extendedAutomaton.setFinalStates(automaton.getFinalStates()); - - for(const auto& transition : automaton.getTransitions()) // pair<State, symb/eps> -> set<State> - for(const auto& to : transition.second) - extendedAutomaton.addTransition(transition.first.first, regexp::RegExp{regexp::UnboundedRegExp(regexp::UnboundedRegExpSymbol(transition.first.second))}, to); - - return extendedAutomaton; -} - -template<> -automaton::ExtendedNFA StateEliminationUnbounded::constructExtendedNFA(const automaton::DFA& automaton) -{ - automaton::ExtendedNFA extendedAutomaton(automaton.getInitialState()); - extendedAutomaton.setStates(automaton.getStates()); - extendedAutomaton.setInputSymbols(automaton.getInputAlphabet()); - extendedAutomaton.setFinalStates(automaton.getFinalStates()); - - for(const auto& transition : automaton.getTransitions()) // pair<State, symb/eps> -> set<State> - extendedAutomaton.addTransition(transition.first.first, regexp::RegExp{regexp::UnboundedRegExp(regexp::UnboundedRegExpSymbol(transition.first.second))}, transition.second); - - return extendedAutomaton; -} - -template<> -automaton::ExtendedNFA StateEliminationUnbounded::constructExtendedNFA(const automaton::EpsilonNFA& automaton) -{ - automaton::ExtendedNFA extendedAutomaton(automaton.getInitialState()); - extendedAutomaton.setStates(automaton.getStates()); - extendedAutomaton.setInputSymbols(automaton.getInputAlphabet()); - extendedAutomaton.setFinalStates(automaton.getFinalStates()); - - for(const auto& transition : automaton.getSymbolTransitions()) // pair<State, symb/eps> -> set<State> - for(const auto& to : transition.second) - extendedAutomaton.addTransition(transition.first.first, regexp::RegExp{regexp::UnboundedRegExp(regexp::UnboundedRegExpSymbol(transition.first.second))}, to); - - for(const auto& transition : automaton.getEpsilonTransitions()) - for(const auto& to : transition.second) - extendedAutomaton.addTransition(transition.first, regexp::RegExp{regexp::UnboundedRegExp(regexp::UnboundedRegExpEpsilon())}, to); - - return extendedAutomaton; -} - -template<> -automaton::ExtendedNFA StateEliminationUnbounded::constructExtendedNFA(const automaton::ExtendedNFA& automaton) -{ - return automaton; -} - -void StateEliminationUnbounded::extendExtendedNFA(automaton::ExtendedNFA& automaton) -{ - const automaton::State& initState = automaton.getInitialState(); - if(automaton.getFinalStates().count(initState) > 0 || automaton.getTransitionsToState(initState).size() > 0 ) - { - const automaton::State q0 = automaton::createUniqueState(initState, automaton.getStates()); - automaton.addState(q0); - - regexp::UnboundedRegExp regexp; - regexp.setRegExp(regexp::UnboundedRegExpEpsilon()); - automaton.addTransition(q0, regexp::RegExp{regexp}, initState); - - automaton.setInitialState(q0); - } - - if(automaton.getFinalStates().size() > 1) - { - const automaton::State f = automaton::createUniqueState(automaton::State("f"), automaton.getStates()); - automaton.addState(f); - - const std::set<automaton::State> automatonFinalStates = automaton.getFinalStates(); - for(const auto &state : automatonFinalStates) - { - regexp::UnboundedRegExp regexp; - regexp.setRegExp(regexp::UnboundedRegExpEpsilon()); - automaton.addTransition(state, regexp::RegExp{regexp}, f); - - automaton.removeFinalState(state); - } - - automaton.addFinalState(f); - } -} - -const StateEliminationUnbounded StateEliminationUnbounded::STATE_ELIMINATION_UNBOUNDED; - -} /* namespace fa2re */ - -} /* namespace conversions */ diff --git a/alib2algo/src/regexp/RegExpAlternate.cpp b/alib2algo/src/regexp/RegExpAlternate.cpp index aad2757955..f080163eff 100644 --- a/alib2algo/src/regexp/RegExpAlternate.cpp +++ b/alib2algo/src/regexp/RegExpAlternate.cpp @@ -10,7 +10,7 @@ namespace regexp { -regexp::RegExp RegExpAlternate::concatenate(const regexp::RegExp& first, const regexp::RegExp& second) +regexp::RegExp RegExpAlternate::alternate(const regexp::RegExp& first, const regexp::RegExp& second) { RegExpBase* out; Accept((void*) &out, first.getData(), second.getData(), RegExpAlternate::REG_EXP_ALTERNATE); @@ -19,12 +19,12 @@ regexp::RegExp RegExpAlternate::concatenate(const regexp::RegExp& first, const r return res; } -regexp::FormalRegExp RegExpAlternate::concatenate(const regexp::FormalRegExp& first, const regexp::FormalRegExp& second) +regexp::FormalRegExp RegExpAlternate::alternate(const regexp::FormalRegExp& first, const regexp::FormalRegExp& second) { return regexp::FormalRegExp(regexp::FormalRegExpAlternation(first.getRegExp(), second.getRegExp())); } -regexp::UnboundedRegExp RegExpAlternate::concatenate(const regexp::UnboundedRegExp& first, const regexp::UnboundedRegExp& second) +regexp::UnboundedRegExp RegExpAlternate::alternate(const regexp::UnboundedRegExp& first, const regexp::UnboundedRegExp& second) { regexp::UnboundedRegExpAlternation con; con.appendElement(first.getRegExp()); @@ -35,13 +35,13 @@ regexp::UnboundedRegExp RegExpAlternate::concatenate(const regexp::UnboundedRegE void RegExpAlternate::Visit(void* data, const regexp::FormalRegExp& first, const regexp::FormalRegExp& second) const { RegExpBase* &ret = *(RegExpBase**) data; - ret = std::move(RegExpAlternate::concatenate(first, second)).plunder(); + ret = std::move(RegExpAlternate::alternate(first, second)).plunder(); } void RegExpAlternate::Visit(void* data, const regexp::UnboundedRegExp& first, const regexp::UnboundedRegExp& second) const { RegExpBase* &ret = *(RegExpBase**) data; - ret = std::move(RegExpAlternate::concatenate(first, second)).plunder(); + ret = std::move(RegExpAlternate::alternate(first, second)).plunder(); } const RegExpAlternate RegExpAlternate::REG_EXP_ALTERNATE; diff --git a/alib2algo/src/regexp/RegExpAlternate.h b/alib2algo/src/regexp/RegExpAlternate.h index 91fd9dd0ae..bb6b3b91ed 100644 --- a/alib2algo/src/regexp/RegExpAlternate.h +++ b/alib2algo/src/regexp/RegExpAlternate.h @@ -22,10 +22,10 @@ namespace regexp class RegExpAlternate : public regexp::VisitableRegExpBase::const_promoting_visitor_type { public: - static regexp::RegExp concatenate(const regexp::RegExp& first, const regexp::RegExp& second); + static regexp::RegExp alternate(const regexp::RegExp& first, const regexp::RegExp& second); - static regexp::FormalRegExp concatenate(const regexp::FormalRegExp& first, const regexp::FormalRegExp& second); - static regexp::UnboundedRegExp concatenate(const regexp::UnboundedRegExp& first, const regexp::UnboundedRegExp& second); + static regexp::FormalRegExp alternate(const regexp::FormalRegExp& first, const regexp::FormalRegExp& second); + static regexp::UnboundedRegExp alternate(const regexp::UnboundedRegExp& first, const regexp::UnboundedRegExp& second); private: void Visit(void* data, const regexp::UnboundedRegExp& first, const regexp::UnboundedRegExp& second) const; -- GitLab