From 20a7c9135a17206bb25d4c70cc9349534f83dbc9 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Mon, 17 Sep 2018 15:32:47 +0200 Subject: [PATCH] template RightRG in automaton to grammar algo --- alib2algo/src/automaton/convert/ToGrammar.h | 2 +- .../automaton/convert/ToGrammarRightRG.cpp | 83 ------------------- .../src/automaton/convert/ToGrammarRightRG.h | 76 ++++++++++++++++- 3 files changed, 73 insertions(+), 88 deletions(-) diff --git a/alib2algo/src/automaton/convert/ToGrammar.h b/alib2algo/src/automaton/convert/ToGrammar.h index 79147ee784..df34d7452d 100644 --- a/alib2algo/src/automaton/convert/ToGrammar.h +++ b/alib2algo/src/automaton/convert/ToGrammar.h @@ -43,7 +43,7 @@ public: /** * Performs the conversion (@sa ToGrammarRightRG::convert). * @tparam SymbolType Type for symbols. - * @tparam StateType Type for states. + * @tparam StateAndNonterminalType Type for states. * @param automaton the automaton to convert * @return right regular grammar equivalent to the input @p automaton */ diff --git a/alib2algo/src/automaton/convert/ToGrammarRightRG.cpp b/alib2algo/src/automaton/convert/ToGrammarRightRG.cpp index b4acef5b64..58e84d9f6f 100644 --- a/alib2algo/src/automaton/convert/ToGrammarRightRG.cpp +++ b/alib2algo/src/automaton/convert/ToGrammarRightRG.cpp @@ -6,95 +6,12 @@ */ #include "ToGrammarRightRG.h" -#include <common/createUnique.hpp> #include <registration/AlgoRegistration.hpp> namespace automaton { namespace convert { -grammar::RightRG < > ToGrammarRightRG::convert(const automaton::NFA < > & automaton) { - ext::map<DefaultStateType, DefaultSymbolType> nonterminalMap; - - const DefaultStateType& initState = automaton.getInitialState(); - DefaultSymbolType initSymbol { initState }; - - grammar::RightRG < > grammar(initSymbol); - nonterminalMap.insert(std::make_pair(initState, initSymbol)); - - grammar.setTerminalAlphabet(automaton.getInputAlphabet()); - - for(const auto& state : automaton.getStates()) { - if(state == initState) - continue; - - DefaultSymbolType nt = common::createUnique(DefaultSymbolType(state), grammar.getTerminalAlphabet(), grammar.getNonterminalAlphabet()); - grammar.addNonterminalSymbol(nt); - nonterminalMap.insert(std::make_pair(state, nt)); - } - - // step 2 - create set of P in G - for(const auto& transition : automaton.getTransitions()) { - const DefaultStateType& from = transition.first.first; - const DefaultSymbolType& input = transition.first.second; - for(const auto& to : transition.second) { - grammar.addRule(nonterminalMap.find(from)->second, ext::make_pair(input, nonterminalMap.find(to)->second)); // 2a - if(automaton.getFinalStates().count(to)) // 2b - grammar.addRule(nonterminalMap.find(from)->second, input); - } - } - - // step 3 - set start symbol of G - grammar.setInitialSymbol(nonterminalMap.find(automaton.getInitialState())->second); - - // step 4 - if(automaton.getFinalStates().count(automaton.getInitialState())) - grammar.setGeneratesEpsilon(true); // okay this feature breaks algorithm but simplifies the code actually :)) - - return grammar; -} - -grammar::RightRG < > ToGrammarRightRG::convert(const automaton::DFA<>& automaton) { - ext::map<DefaultStateType, DefaultSymbolType> nonterminalMap; - - const DefaultStateType& initState = automaton.getInitialState(); - DefaultSymbolType initSymbol { initState }; - - grammar::RightRG < > grammar(initSymbol); - nonterminalMap.insert(std::make_pair(initState, initSymbol)); - - grammar.setTerminalAlphabet(automaton.getInputAlphabet()); - - for(const auto& state : automaton.getStates()) { - if(state == initState) - continue; - - DefaultSymbolType nt = common::createUnique(DefaultSymbolType(state), grammar.getTerminalAlphabet(), grammar.getNonterminalAlphabet()); - grammar.addNonterminalSymbol(nt); - nonterminalMap.insert(std::make_pair(state, nt)); - } - - // step 2 - create set of P in G - for(const auto& transition : automaton.getTransitions()) { - const DefaultStateType& from = transition.first.first; - const DefaultSymbolType& input = transition.first.second; - const DefaultStateType& to = transition.second; - - grammar.addRule(nonterminalMap.find(from)->second, ext::make_pair(input, nonterminalMap.find(to)->second)); // 2a - if(automaton.getFinalStates().count(to)) // 2b - grammar.addRule(nonterminalMap.find(from)->second, input); - } - - // step 3 - set start symbol of G - grammar.setInitialSymbol(nonterminalMap.find(automaton.getInitialState())->second); - - // step 4 - if(automaton.getFinalStates().count(automaton.getInitialState())) - grammar.setGeneratesEpsilon(true); // okay this feature breaks algorithm but simplifies the code actually :)) - - return grammar; -} - auto ToGrammarRightRGNFA = registration::AbstractRegister < ToGrammarRightRG, grammar::RightRG < >, const automaton::NFA < > & > ( ToGrammarRightRG::convert ); auto ToGrammarRightRGDFA = registration::AbstractRegister < ToGrammarRightRG, grammar::RightRG < >, const automaton::DFA < > & > ( ToGrammarRightRG::convert ); diff --git a/alib2algo/src/automaton/convert/ToGrammarRightRG.h b/alib2algo/src/automaton/convert/ToGrammarRightRG.h index d3d29ee789..f72eab3bd5 100644 --- a/alib2algo/src/automaton/convert/ToGrammarRightRG.h +++ b/alib2algo/src/automaton/convert/ToGrammarRightRG.h @@ -25,9 +25,12 @@ #define __TO_GRAMMAR_RIGHT_RG_H__ #include <grammar/Regular/RightRG.h> + #include <automaton/FSM/NFA.h> #include <automaton/FSM/DFA.h> +#include <common/createUnique.hpp> + namespace automaton { namespace convert { @@ -39,17 +42,82 @@ class ToGrammarRightRG { public: /** * Performs the conversion of the finite automaton to right regular grammar. - * @param automaton a finite automaton to convert - * @return right regular grammar equivalent to the source @p automaton. + * + * \tparam SymbolType the type of input/terminal symbols of automaton and the resulting grammar + * \tparam StateNonterminalType the type of states of the automaton and nonterminal symbols of the resulting grammar + * + * \param automaton a finite automaton to convert + * + * \return right regular grammar equivalent to the source @p automaton. */ - static grammar::RightRG < > convert(const automaton::NFA < > & automaton); + template < class SymbolType, class StateNonterminalType > + static grammar::RightRG < SymbolType, StateNonterminalType > convert ( const automaton::NFA < SymbolType, StateNonterminalType > & automaton ); /** * \overload */ - static grammar::RightRG < > convert(const automaton::DFA < > & automaton); + template < class SymbolType, class StateNonterminalType > + static grammar::RightRG < SymbolType, StateNonterminalType > convert ( const automaton::DFA < SymbolType, StateNonterminalType > & automaton ); }; + +template < class SymbolType, class StateNonterminalType > +grammar::RightRG < SymbolType, StateNonterminalType > ToGrammarRightRG::convert ( const automaton::NFA < SymbolType, StateNonterminalType > & automaton ) { + grammar::RightRG < SymbolType, StateNonterminalType > grammar ( automaton.getInitialState ( ) ); + + grammar.setTerminalAlphabet ( automaton.getInputAlphabet ( ) ); + grammar.setNonterminalAlphabet ( automaton.getStates ( ) ); + + // step 2 - create set of P in G + for(const auto& transition : automaton.getTransitions()) { + const auto & from = transition.first.first; + const auto & input = transition.first.second; + + for(const auto& to : transition.second) { + grammar.addRule ( from, ext::make_pair ( input, to ) ); // 2a + if(automaton.getFinalStates().count(to)) // 2b + grammar.addRule(transition.first.first, transition.first.second ); + } + } + + // step 3 - set start symbol of G + grammar.setInitialSymbol(automaton.getInitialState()); + + // step 4 + if(automaton.getFinalStates().count(automaton.getInitialState())) + grammar.setGeneratesEpsilon(true); // okay this feature makes the algorithm a bit different but at the same time it simplifies the code :)) + + return grammar; +} + +template < class SymbolType, class StateNonterminalType > +grammar::RightRG < SymbolType, StateNonterminalType > ToGrammarRightRG::convert ( const automaton::DFA < SymbolType, StateNonterminalType > & automaton ) { + grammar::RightRG < SymbolType, StateNonterminalType > grammar ( automaton.getInitialState ( ) ); + + grammar.setTerminalAlphabet ( automaton.getInputAlphabet ( ) ); + grammar.setNonterminalAlphabet ( automaton.getStates ( ) ); + + // step 2 - create set of P in G + for(const auto& transition : automaton.getTransitions()) { + const auto & from = transition.first.first; + const auto & input = transition.first.second; + const auto & to = transition.second; + + grammar.addRule(from, ext::make_pair(input, to)); // 2a + if(automaton.getFinalStates().count(to)) // 2b + grammar.addRule(from, input); + } + + // step 3 - set start symbol of G + grammar.setInitialSymbol ( automaton.getInitialState ( ) ); + + // step 4 + if ( automaton.getFinalStates ( ).count ( automaton.getInitialState ( ) ) ) + grammar.setGeneratesEpsilon(true); // okay this feature makes the algorithm a bit different but at the same time it simplifies the code :)) + + return grammar; +} + } /* namespace convert */ } /* namespace automaton */ -- GitLab