From 5e1b37737741ee2aa9555ed4ee449e2963594bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Pecka?= <peckato1@fit.cvut.cz> Date: Sat, 6 Sep 2014 22:09:59 +0200 Subject: [PATCH] algo: conv: fa2rg, rg2fa --- .../src/fa2rg/fa2lrg/FAtoLRGConverter.cpp | 92 ---------------- .../src/fa2rg/fa2lrg/FAtoLRGConverter.h | 45 -------- .../src/fa2rg/fa2rrg/FAtoRRGConverter.cpp | 100 ------------------ .../src/fa2rg/fa2rrg/FAtoRRGConverter.h | 45 -------- .../src/rg2fa/lrg2fa/LRGtoFAConverter.cpp | 68 ------------ .../src/rg2fa/lrg2fa/LRGtoFAConverter.h | 41 ------- .../src/rg2fa/rrg2fa/RRGtoFAConverter.cpp | 66 ------------ .../src/rg2fa/rrg2fa/RRGtoFAConverter.h | 41 ------- aconversions2/src/ConversionHandler.cpp | 35 +++--- .../fa2rg/fa2lrg/FAtoLRGConverter.cpp | 58 ++++++++++ .../fa2rg/fa2lrg/FAtoLRGConverter.h | 28 +++++ .../fa2rg/fa2rrg/FAtoRRGConverter.cpp | 91 ++++++++++++++++ .../fa2rg/fa2rrg/FAtoRRGConverter.h | 29 +++++ .../rg2fa/lrg2fa/LRGtoFAConverter.cpp | 56 ++++++++++ .../rg2fa/lrg2fa/LRGtoFAConverter.h | 26 +++++ .../rg2fa/rrg2fa/RRGtoFAConverter.cpp | 57 ++++++++++ .../rg2fa/rrg2fa/RRGtoFAConverter.h | 26 +++++ 17 files changed, 387 insertions(+), 517 deletions(-) delete mode 100644 aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.cpp delete mode 100644 aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.h delete mode 100644 aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.cpp delete mode 100644 aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.h delete mode 100644 aconversions/src/rg2fa/lrg2fa/LRGtoFAConverter.cpp delete mode 100644 aconversions/src/rg2fa/lrg2fa/LRGtoFAConverter.h delete mode 100644 aconversions/src/rg2fa/rrg2fa/RRGtoFAConverter.cpp delete mode 100644 aconversions/src/rg2fa/rrg2fa/RRGtoFAConverter.h create mode 100644 alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.cpp create mode 100644 alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.h create mode 100644 alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.cpp create mode 100644 alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.h create mode 100644 alib2algo/src/conversions/rg2fa/lrg2fa/LRGtoFAConverter.cpp create mode 100644 alib2algo/src/conversions/rg2fa/lrg2fa/LRGtoFAConverter.h create mode 100644 alib2algo/src/conversions/rg2fa/rrg2fa/RRGtoFAConverter.cpp create mode 100644 alib2algo/src/conversions/rg2fa/rrg2fa/RRGtoFAConverter.h diff --git a/aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.cpp b/aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.cpp deleted file mode 100644 index 253fcf940a..0000000000 --- a/aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include "FAtoLRGConverter.h" - -using namespace std; -using namespace automaton; -using namespace grammar; -using namespace alib; - -namespace conversions -{ - -FAtoLRGConverter::FAtoLRGConverter( const FSM & automaton ) : m_automaton( automaton ) -{ - if( ! automaton.isEpsilonFree( ) ) - throw AlibException( "FSM has epsilon transitions." ); -} - -FAtoLRGConverter::~FAtoLRGConverter( void ) -{ - -} - -LeftRegularGrammar FAtoLRGConverter::convert( void ) -{ - LeftRegularGrammar grammar; - map<State, Symbol> nonterminalMap; - - for( const auto & symbol : m_automaton.getInputAlphabet( ) ) - grammar.addTerminalSymbol( symbol ); - - for( const auto & state : m_automaton.getStates( ) ) - { - Symbol nt = grammar.createUniqueNonTerminalSymbol( state.getName( ) ); - nonterminalMap.insert( pair<State,Symbol>( state, nt ) ); - } - - // step 2 - Symbol newStart = grammar.createUniqueNonTerminalSymbol( "S", false ); - grammar.setStartSymbol( newStart ); - - // step 3 - create set of P in G - for( const auto & transition : m_automaton.getTransitions( ) ) - { - // 3a - list<Symbol> leftSide, rightSide; - leftSide.push_back( nonterminalMap.find( transition.getTo( ) )->second ); - rightSide.push_back( nonterminalMap.find( transition.getFrom( ) )->second ); - rightSide.push_back( transition.getInput( ) ); - grammar.addRule( Rule( leftSide, rightSide ) ); - - if( isInSet( transition.getTo( ), m_automaton.getFinalStates( ) ) ) - { - list<Symbol> leftSide, rightSide; - leftSide.push_back( grammar.getStartSymbol( ) ); - rightSide.push_back( nonterminalMap.find( transition.getFrom( ) )->second ); - rightSide.push_back( transition.getInput( ) ); - - Rule r( leftSide, rightSide ); - if( ! isInSet( r, grammar.getRules( ) ) ) - grammar.addRule( Rule( leftSide, rightSide ) ); - } - - - if( isInSet( transition.getFrom( ), m_automaton.getInitialStates( ) ) ) - { - list<Symbol> leftSide, rightSide; - leftSide.push_back( nonterminalMap.find( transition.getTo( ) )->second ); - rightSide.push_back( transition.getInput( ) ); - grammar.addRule( Rule( leftSide, rightSide ) ); - - if( isInSet( transition.getTo( ), m_automaton.getFinalStates( ) ) ) - { - list<Symbol> leftSide, rightSide; - leftSide.push_back( grammar.getStartSymbol( ) ); - rightSide.push_back( transition.getInput( ) ); - - Rule r( leftSide, rightSide ); - if( ! isInSet( r, grammar.getRules( ) ) ) - grammar.addRule( Rule( leftSide, rightSide ) ); - } - } - } - - if( isInSet( * m_automaton.getInitialStates( ).begin( ), m_automaton.getFinalStates( ) ) ) - { - list<Symbol> leftSide = { newStart }, rightSide; - grammar.addRule( Rule( leftSide, rightSide ) ); - } - - return grammar; -} - -} /* namespace conversions */ diff --git a/aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.h b/aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.h deleted file mode 100644 index 8d47a792c0..0000000000 --- a/aconversions/src/fa2rg/fa2lrg/FAtoLRGConverter.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __FATOLRGCONVERTER_H__ -#define __FATOLRGCONVERTER_H__ - -#include <map> - -#include <grammar/Regular/LeftRegularGrammar.h> -#include <automaton/FSM/FSM.h> -#include <AlibException.h> - -#include "../../interface/IConversionLRG.h" -#include "../../include/macros.h" - -namespace conversions -{ - -/** - * Finite automaton to right regular grammar converter. - * Source: My own :) - */ -class FAtoLRGConverter: public IConversionLRG -{ -public: - /** - * @param automaton Original automaton. - */ - FAtoLRGConverter( const automaton::FSM & automaton ); - - ~FAtoLRGConverter( void ); - - /** - * Performs conversion. - * @return left regular grammar equivalent to source automaton. - */ - grammar::LeftRegularGrammar convert( void ); - -protected: - /** - * input automaton - */ - const automaton::FSM & m_automaton; -}; - -} /* namespace conversions */ - -#endif /* __FATOLRGCONVERTER_H__ */ diff --git a/aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.cpp b/aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.cpp deleted file mode 100644 index 4a87c0a6d2..0000000000 --- a/aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "FAtoRRGConverter.h" - -using namespace std; -using namespace automaton; -using namespace grammar; -using namespace alib; - -namespace conversions -{ - -FAtoRRGConverter::FAtoRRGConverter( const FSM & automaton ) : m_automaton( automaton ) -{ - if( ! automaton.isEpsilonFree( ) ) - throw AlibException( "FSM has epsilon transitions." ); -} - -FAtoRRGConverter::~FAtoRRGConverter( void ) -{ - -} - -RightRegularGrammar FAtoRRGConverter::convert( void ) -{ - RightRegularGrammar grammar; - map<State, Symbol> nonterminalMap; - - for( const auto & symbol : m_automaton.getInputAlphabet( ) ) - grammar.addTerminalSymbol( symbol ); - - for( const auto & state : m_automaton.getStates( ) ) - { - Symbol nt = grammar.createUniqueNonTerminalSymbol( state.getName( ) ); - nonterminalMap.insert( pair<State,Symbol>( state, nt ) ); - } - - // step 2 - create set of P in G - for( const auto & transition : m_automaton.getTransitions( ) ) - { - // 2a - list<Symbol> leftSide, rightSide; - leftSide.push_back( nonterminalMap.find( transition.getFrom( ) )->second ); - rightSide.push_back( transition.getInput( ) ); - rightSide.push_back( nonterminalMap.find( transition.getTo( ) )->second ); - grammar.addRule( Rule( leftSide, rightSide ) ); - - // 2b - if( isInSet( transition.getTo( ), m_automaton.getFinalStates( ) ) ) - { - list<Symbol> leftSide, rightSide; - leftSide.push_back( nonterminalMap.find( transition.getFrom( ) )->second ); - rightSide.push_back( transition.getInput( ) ); - - /* - * Rule might already in - consider case: - * \delta(A,a) = { F, G }, where both F and G are final states - */ - if( ! isInSet( Rule( leftSide, rightSide), grammar.getRules( ) ) ) - grammar.addRule( Rule( leftSide, rightSide ) ); - } - } - - // step 3 - set start symbol of G - grammar.setStartSymbol( nonterminalMap.find( * m_automaton.getInitialStates( ).begin( ) )->second ); - - // step 4 - if( isInSet( * m_automaton.getInitialStates( ).begin( ), m_automaton.getFinalStates( ) ) ) - { - // 4a - if( ! grammar.isNonTerminalOnRightSideOfAnyRule( grammar.getStartSymbol( ) ) ) - { - list<Symbol> leftSide, rightSide; - leftSide.push_back( grammar.getStartSymbol( ) ); - grammar.addRule( Rule( leftSide, rightSide ) ); - } - else // 4b - { - Symbol newStart = grammar.createUniqueNonTerminalSymbol( grammar.getStartSymbol( ).getSymbol( ), false ); - - for( const auto & rule : grammar.getRules( ) ) - { - if( rule.getLeftSide( ).front( ) == grammar.getStartSymbol( ) ) - { - list<Symbol> leftSide, rightSide( rule.getRightSide( ) ); - leftSide.push_back( newStart ); - grammar.addRule( Rule( leftSide, rightSide ) ); - } - } - grammar.setStartSymbol( newStart ); - - list<Symbol> leftSide, rightSide; - leftSide.push_back( newStart ); - Rule rr( leftSide, rightSide ); - grammar.addRule( Rule( leftSide, rightSide ) ); - } - } - - return grammar; -} - -} /* namespace conversions */ diff --git a/aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.h b/aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.h deleted file mode 100644 index cf0b442f64..0000000000 --- a/aconversions/src/fa2rg/fa2rrg/FAtoRRGConverter.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __FATORRGCONVERTER_H__ -#define __FATORRGCONVERTER_H__ - -#include <map> - -#include <grammar/Regular/RightRegularGrammar.h> -#include <automaton/FSM/FSM.h> -#include <AlibException.h> - -#include "../../interface/IConversionRRG.h" -#include "../../include/macros.h" - -namespace conversions -{ - -/** - * Finite automaton to right regular grammar converter. - * Source: Melichar 2.104 - */ -class FAtoRRGConverter : public IConversionRRG -{ -public: - /** - * @param automaton Source automaton. - */ - FAtoRRGConverter( const automaton::FSM & automaton ); - - ~FAtoRRGConverter( void ); - - /** - * Performs conversion. - * @return left regular grammar equivalent to source automaton. - */ - grammar::RightRegularGrammar convert ( void ); - -protected: - /** - * input automaton - */ - const automaton::FSM & m_automaton; -}; - -} /* namespace conversions */ - -#endif /* __FATORRGCONVERTER_H__ */ diff --git a/aconversions/src/rg2fa/lrg2fa/LRGtoFAConverter.cpp b/aconversions/src/rg2fa/lrg2fa/LRGtoFAConverter.cpp deleted file mode 100644 index dd06004fcb..0000000000 --- a/aconversions/src/rg2fa/lrg2fa/LRGtoFAConverter.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "LRGtoFAConverter.h" - -using namespace alphabet; -using namespace automaton; -using namespace grammar; - -namespace conversions -{ - -LRGtoFAConverter::LRGtoFAConverter( const LeftRegularGrammar & grammar ) : m_grammar( grammar ) -{ - -} - -LRGtoFAConverter::~LRGtoFAConverter( void ) -{ - -} - -FSM LRGtoFAConverter::convert( void ) -{ - FSM automaton; - - for( const auto & symbol : m_grammar.getTerminalSymbols( ) ) - automaton.addInputSymbol( symbol ); - - for( const auto & symbol : m_grammar.getNonTerminalSymbols( ) ) - automaton.addState( State( symbol.getSymbol( ) ) ); - - const State & startState = automaton.createUniqueState( "q0", true ); - - // step 3, constructing \delta - for( const auto & rule : m_grammar.getRules( ) ) - { - if( m_grammar.isEpsilonRule( rule ) ) - continue; - - State current( rule.getLeftSide( ).front( ).getSymbol( ) ); - - // if B->a => \delta(StartState,a)=B - if( rule.getRightSide( ).size( ) == 1 ) - { - const Symbol & input( rule.getRightSide( ).front( ).getSymbol( ) ); - automaton.addTransition( startState, input, current ); - } - // if B->Ca => \delta(C,a)=B - else if( rule.getRightSide( ).size( ) == 2 ) - { - State next( rule.getRightSide( ).front( ).getSymbol( ) ); - const Symbol & input = rule.getRightSide( ).back( ); - - automaton.addTransition( next, input, current ); - } - } - - // step 4 - automaton.addInitialState( startState ); - - // step 5 - automaton.addFinalState( State( m_grammar.getStartSymbol().getSymbol() ) ); - for( const auto & rule : m_grammar.getRules( ) ) - if( m_grammar.isEpsilonRule( rule ) ) - automaton.addFinalState( startState ); - - return automaton; -} - -} /* namespace conversions */ diff --git a/aconversions/src/rg2fa/lrg2fa/LRGtoFAConverter.h b/aconversions/src/rg2fa/lrg2fa/LRGtoFAConverter.h deleted file mode 100644 index 6fc54f6e13..0000000000 --- a/aconversions/src/rg2fa/lrg2fa/LRGtoFAConverter.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __LRGTOFACONVERTER_H__ -#define __LRGTOFACONVERTER_H__ - -#include <grammar/Regular/LeftRegularGrammar.h> -#include <automaton/FSM/FSM.h> - -#include "../../interface/IConversionFSM.h" - -namespace conversions -{ - -/** - * Converts left regular grammar to finite automaton. - * Source: Melichar 2.102. - */ -class LRGtoFAConverter : public IConversionFSM -{ -public: - /** - * @param grammar Source left regular grammar. - */ - LRGtoFAConverter( const grammar::LeftRegularGrammar & grammar ); - - ~LRGtoFAConverter( void ); - - /** - * Performs conversion. - * @return FSM equivalent to source grammar. - */ - automaton::FSM convert( void ); - -private: - /** - * input grammar - */ - const grammar::LeftRegularGrammar & m_grammar; -}; - -} /* namespace conversions */ - -#endif /* __LRGTOFACONVERTER_H__ */ diff --git a/aconversions/src/rg2fa/rrg2fa/RRGtoFAConverter.cpp b/aconversions/src/rg2fa/rrg2fa/RRGtoFAConverter.cpp deleted file mode 100644 index 8c81927b11..0000000000 --- a/aconversions/src/rg2fa/rrg2fa/RRGtoFAConverter.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "RRGtoFAConverter.h" - -using namespace alphabet; -using namespace automaton; -using namespace grammar; - -namespace conversions -{ - -RRGtoFAConverter::RRGtoFAConverter( const RightRegularGrammar & grammar ) : m_grammar( grammar ) -{ - -} - -RRGtoFAConverter::~RRGtoFAConverter( void ) -{ - -} - - -FSM RRGtoFAConverter::convert( void ) -{ - FSM automaton; - - for( const auto & symbol : m_grammar.getTerminalSymbols( ) ) - automaton.addInputSymbol( symbol ); - - for( const auto & symbol : m_grammar.getNonTerminalSymbols( ) ) - automaton.addState( State( symbol.getSymbol( ) ) ); - - const State & AState = automaton.createUniqueState( "A", false ); - - for( const auto & rule : m_grammar.getRules( ) ) - { - if( m_grammar.isEpsilonRule( rule ) ) - continue; - - State current( rule.getLeftSide( ).front( ).getSymbol( ) ); - - if( rule.getRightSide( ).size( ) == 1 ) // if B->a => \delta(B,a)=AState - { - const Symbol & input( rule.getRightSide( ).front( ).getSymbol( ) ); - automaton.addTransition( current, input, AState ); - } - else if( rule.getRightSide( ).size( ) == 2 ) // if B->aC => \delta(B,a)=C - { - const Symbol & input = rule.getRightSide( ).front( ); - State next( rule.getRightSide( ).back( ).getSymbol( ) ); - - automaton.addTransition( current, input, next ); - } - } - - // step 4 - automaton.addInitialState( m_grammar.getStartSymbol().getSymbol() ); - - // step 5 - automaton.addFinalState( AState ); - for( const auto & rule : m_grammar.getRules( ) ) - if( m_grammar.isEpsilonRule( rule ) ) - automaton.addFinalState( State( m_grammar.getStartSymbol( ).getSymbol( ) ) ); - - return automaton; -} - -} /* namespace conversions */ diff --git a/aconversions/src/rg2fa/rrg2fa/RRGtoFAConverter.h b/aconversions/src/rg2fa/rrg2fa/RRGtoFAConverter.h deleted file mode 100644 index edb23c86d5..0000000000 --- a/aconversions/src/rg2fa/rrg2fa/RRGtoFAConverter.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __RRGTOFACONVERTER_H__ -#define __RRGTOFACONVERTER_H__ - -#include <grammar/Regular/RightRegularGrammar.h> -#include <automaton/FSM/FSM.h> - -#include "../../interface/IConversionFSM.h" - -namespace conversions -{ - -/** - * Converts left regular grammar to finite automaton. - * Source: Melichar 2.98 - */ -class RRGtoFAConverter : public IConversionFSM -{ -public: - /** - * @param grammar Source right regular grammar. - */ - RRGtoFAConverter( const grammar::RightRegularGrammar & grammar ); - - ~RRGtoFAConverter( void ); - - /** - * Performs conversion. - * @return FSM equivalent to source grammar. - */ - automaton::FSM convert( void ); - -private: - /** - * input grammar - */ - const grammar::RightRegularGrammar & m_grammar; -}; - -} /* namespace conversions */ - -#endif /* __RRGTOFACONVERTER_H__ */ diff --git a/aconversions2/src/ConversionHandler.cpp b/aconversions2/src/ConversionHandler.cpp index 9f40da9e86..814185c436 100644 --- a/aconversions2/src/ConversionHandler.cpp +++ b/aconversions2/src/ConversionHandler.cpp @@ -14,11 +14,11 @@ //#include "conversions/re2fa/Thompson.h" //#include "conversions/re2fa/Brzozowski.h" -//#include "conversions/fa2rg/fa2lrg/FAtoLRGConverter.h" -//#include "conversions/fa2rg/fa2rrg/FAtoRRGConverter.h" +#include "conversions/fa2rg/fa2lrg/FAtoLRGConverter.h" +#include "conversions/fa2rg/fa2rrg/FAtoRRGConverter.h" -//#include "conversions/rg2fa/lrg2fa/LRGtoFAConverter.h" -//#include "conversions/rg2fa/rrg2fa/RRGtoFAConverter.h" +#include "conversions/rg2fa/lrg2fa/LRGtoFAConverter.h" +#include "conversions/rg2fa/rrg2fa/RRGtoFAConverter.h" //#include "conversions/rg2re/rrg2re/RRGAlgebraic.h" //#include "conversions/rg2re/lrg2re/LRGAlgebraic.h" @@ -148,9 +148,8 @@ void ConversionHandler::convertFSMtoRRG( void ) switch( m_algorithm ) { default: { -/* fa2rg::FAtoRRGConverter conv( fsm ); - regexp::UnboundedRegExp re = conv.convert(); - alib::DataFactory::toStdout(re);*/ + fa2rg::FAtoRRGConverter conv; + alib::DataFactory::toStdout(conv.convert(fsm)); break; } } @@ -163,9 +162,8 @@ void ConversionHandler::convertFSMtoLRG( void ) switch( m_algorithm ) { default: { -/* fa2rg::FAtoLRGConverter conv( fsm ); - regexp::UnboundedRegExp re = conv.convert(); - alib::DataFactory::toStdout(re);*/ + fa2rg::FAtoLRGConverter conv; + alib::DataFactory::toStdout(conv.convert(fsm)); break; } } @@ -283,9 +281,8 @@ void ConversionHandler::convertLRGtoFSM( void ) switch( m_algorithm ) { default: { -/* rg2fa::LRGtoFAConverter conv( lrg ); - automaton::NFA nfa = conv.convert(); - alib::DataFactory::toStdout(nfa);*/ + rg2fa::LRGtoFAConverter conv; + alib::DataFactory::toStdout(conv.convert(lrg)); break; } } @@ -298,9 +295,8 @@ void ConversionHandler::convertRRGtoFSM( void ) switch( m_algorithm ) { default: { -/* rg2fa::RRGtoFAConverter conv( lrg ); - automaton::NFA nfa = conv.convert(); - alib::DataFactory::toStdout(nfa);*/ + rg2fa::RRGtoFAConverter conv; + alib::DataFactory::toStdout(conv.convert(rrg)); break; } } @@ -399,10 +395,11 @@ ConversionHandler::TFormalism ConversionHandler::parseFormalismFromTokens( void if( xmlMark == "regexp" || xmlMark == "unboundedRegexp" ) return REGULAR_EXPRESSION; - if( xmlMark == "grammar" ) - { + if( xmlMark == "RightRG" ) return RIGHT_REGULAR_GRAMMAR; - } + + if( xmlMark == "LeftRG" ) + return LEFT_REGULAR_GRAMMAR; throw exception::AlibException( "ConversionHandler: Invalid input formalism." ); } diff --git a/alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.cpp b/alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.cpp new file mode 100644 index 0000000000..aa02f30771 --- /dev/null +++ b/alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.cpp @@ -0,0 +1,58 @@ +#include "FAtoLRGConverter.h" +#include <map> + +#include <label/StringLabel.h> +#include <alphabet/LabeledSymbol.h> + +namespace fa2rg +{ + +grammar::LeftRG FAtoLRGConverter::convert(const automaton::NFA& automaton) +{ + std::map<automaton::State, alphabet::Symbol> nonterminalMap; + // step 2 + grammar::LeftRG grammar(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("S"))))); + + // step 1 + grammar.setTerminalAlphabet(automaton.getInputAlphabet()); + + for(const auto& state : automaton.getStates()) + { + alphabet::Symbol nt = alphabet::createUniqueSymbol(alphabet::Symbol(alphabet::LabeledSymbol(state.getName())), grammar.getTerminalAlphabet(), grammar.getNonterminalAlphabet()); + grammar.addNonterminalSymbol(nt); + nonterminalMap.insert(std::pair<automaton::State, alphabet::Symbol>(state, nt)); + } + + + // step 3 - create set of P in G + for(const auto& transition : automaton.getTransitions()) + { + const automaton::State& from = transition.first.first; + const alphabet::Symbol& input = transition.first.second; + + for(const auto& to : transition.second) + { + // 3a + grammar.addRule(nonterminalMap.find(to)->second, std::make_pair(nonterminalMap.find(from)->second, input)); + + if(automaton.getFinalStates().count(to) > 0) + grammar.addRule(grammar.getInitialSymbol(), std::make_pair(nonterminalMap.find(from)->second, input)); + + + if(automaton.getInitialStates().count(from) > 0) + { + grammar.addRule(nonterminalMap.find(to)->second, input); + + if(automaton.getFinalStates().count(to) > 0) + grammar.addRule(grammar.getInitialSymbol(), input); + } + } + } + + if(automaton.getFinalStates().count(*automaton.getInitialStates().begin()) > 0) + grammar.setGeneratesEpsilon(true); + + return grammar; +} + +} /* namespace fa2rg */ diff --git a/alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.h b/alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.h new file mode 100644 index 0000000000..ef2f0a32ac --- /dev/null +++ b/alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.h @@ -0,0 +1,28 @@ +#ifndef __FATOLRGCONVERTER_H__ +#define __FATOLRGCONVERTER_H__ + +#include <map> + +#include <grammar/Regular/LeftRG.h> +#include <automaton/FSM/NFA.h> + +namespace fa2rg +{ + +/** + * Finite automaton to right regular grammar converter. + * Source: My own :) + */ +class FAtoLRGConverter +{ +public: + /** + * Performs conversion. + * @return left regular grammar equivalent to source automaton. + */ + grammar::LeftRG convert(const automaton::NFA& automaton); +}; + +} /* namespace fa2rg */ + +#endif /* __FATOLRGCONVERTER_H__ */ diff --git a/alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.cpp b/alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.cpp new file mode 100644 index 0000000000..6fc273e1a8 --- /dev/null +++ b/alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.cpp @@ -0,0 +1,91 @@ +#include "FAtoRRGConverter.h" + +#include <alphabet/LabeledSymbol.h> + +namespace fa2rg +{ + +grammar::RightRG FAtoRRGConverter::convert(const automaton::NFA& automaton) +{ + std::map<automaton::State, alphabet::Symbol> nonterminalMap; + + const automaton::State& initState = *automaton.getInitialStates().begin(); + const alphabet::Symbol initSymbol(alphabet::LabeledSymbol(initState.getName())); + + 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; + + alphabet::Symbol nt = alphabet::createUniqueSymbol(alphabet::Symbol(alphabet::LabeledSymbol(state.getName())), 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 automaton::State& from = transition.first.first; + const alphabet::Symbol& input = transition.first.second; + for(const auto& to : transition.second) + { + grammar.addRule(nonterminalMap.find(from)->second, std::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.getInitialStates().begin())->second); + + // step 4 + if(automaton.getFinalStates().count(*automaton.getInitialStates().begin())) + { + if( ! this->isSymbolOnAnyRightHandSide(grammar.getInitialSymbol(), grammar)) // 4a + { + grammar.setGeneratesEpsilon(true); + } + else // 4b + { + alphabet::Symbol newStart = alphabet::createUniqueSymbol(grammar.getInitialSymbol(), grammar.getTerminalAlphabet(), grammar.getNonterminalAlphabet()); + grammar.addNonterminalSymbol(newStart); + + for(const auto& rule : grammar.getRules()) + for(const auto& rightSide : rule.second) + if(rule.first == grammar.getInitialSymbol()) + grammar.addRule(newStart, rightSide); + + grammar.setInitialSymbol(newStart); + grammar.setGeneratesEpsilon(true); + } + } + + return grammar; +} + +bool FAtoRRGConverter::isSymbolOnAnyRightHandSide(const alphabet::Symbol& symbol, const grammar::RightRG& grammar) const +{ + for(const auto& rule : grammar.getRules()) + for(const auto& rightSide : rule.second) + if(rightSide.is<std::pair<alphabet::Symbol, alphabet::Symbol>>( )) + { + const std::pair<alphabet::Symbol, alphabet::Symbol>& rhs = rightSide.get<std::pair<alphabet::Symbol, alphabet::Symbol>>(); + if(rhs.first == symbol || rhs.second == symbol) + return true; + } + else + { + const alphabet::Symbol& rhs = rightSide.get<alphabet::Symbol>(); + if(rhs == symbol) + return true; + } + + return false; +} + +} /* namespace fa2rg */ diff --git a/alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.h b/alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.h new file mode 100644 index 0000000000..79132db839 --- /dev/null +++ b/alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.h @@ -0,0 +1,29 @@ +#ifndef __FATORRGCONVERTER_H__ +#define __FATORRGCONVERTER_H__ + +#include <grammar/Regular/RightRG.h> +#include <automaton/FSM/NFA.h> + +namespace fa2rg +{ + +/** + * Finite automaton to right regular grammar converter. + * Source: Melichar 2.104 + */ +class FAtoRRGConverter +{ +public: + /** + * Performs conversion. + * @return left regular grammar equivalent to source automaton. + */ + grammar::RightRG convert(const automaton::NFA& automaton); + +private: + bool isSymbolOnAnyRightHandSide(const alphabet::Symbol& symbol, const grammar::RightRG& grammar) const; +}; + +} /* namespace fa2rg */ + +#endif /* __FATORRGCONVERTER_H__ */ diff --git a/alib2algo/src/conversions/rg2fa/lrg2fa/LRGtoFAConverter.cpp b/alib2algo/src/conversions/rg2fa/lrg2fa/LRGtoFAConverter.cpp new file mode 100644 index 0000000000..01d719f8e2 --- /dev/null +++ b/alib2algo/src/conversions/rg2fa/lrg2fa/LRGtoFAConverter.cpp @@ -0,0 +1,56 @@ +#include "LRGtoFAConverter.h" + +#include <label/StringLabel.h> +#include <automaton/Automaton.h> +#include <alphabet/LabeledSymbol.h> + +namespace rg2fa +{ + +automaton::NFA LRGtoFAConverter::convert(const grammar::LeftRG& grammar) +{ + std::map<alphabet::Symbol, automaton::State> stateMap; + + automaton::NFA automaton; + automaton.setInputSymbols(grammar.getTerminalAlphabet()); + for(const auto& symbol : grammar.getNonterminalAlphabet()) + { + automaton::State state(static_cast<const alphabet::LabeledSymbol&>(symbol.getData()).getLabel()); + automaton.addState(state); + stateMap.insert(std::make_pair(symbol, state)); + } + + const automaton::State startState = automaton::createUniqueState(automaton::State(label::Label(label::StringLabel("q0"))), automaton.getStates()); + automaton.addState(startState); + + // step 3, constructing \delta + for(const auto& rule : grammar.getRules()) + { + const alphabet::Symbol& lhs = rule.first; + for(const auto& ruleRHS : rule.second) + { + if(ruleRHS.is<std::pair<alphabet::Symbol, alphabet::Symbol>>()) // if B->Ca => \delta(C,a)=B + { + const std::pair<alphabet::Symbol, alphabet::Symbol>& rhs = ruleRHS.get<std::pair<alphabet::Symbol, alphabet::Symbol>>(); + automaton.addTransition(stateMap.find(rhs.first)->second, rhs.second, stateMap.find(lhs)->second); + } + else // if B->a => \delta(StartState,a)=B + { + const alphabet::Symbol& rhs = ruleRHS.get<alphabet::Symbol>(); + automaton.addTransition(startState, rhs, stateMap.find(lhs)->second); + } + } + } + + // step 4 + automaton.addInitialState(startState); + + // step 5 + automaton.addFinalState(stateMap.find(grammar.getInitialSymbol())->second); + if(grammar.getGeneratesEpsilon()) + automaton.addFinalState(startState); + + return automaton; +} + +} /* namespace rg2fa */ diff --git a/alib2algo/src/conversions/rg2fa/lrg2fa/LRGtoFAConverter.h b/alib2algo/src/conversions/rg2fa/lrg2fa/LRGtoFAConverter.h new file mode 100644 index 0000000000..607f72d46d --- /dev/null +++ b/alib2algo/src/conversions/rg2fa/lrg2fa/LRGtoFAConverter.h @@ -0,0 +1,26 @@ +#ifndef __LRGTOFACONVERTER_H__ +#define __LRGTOFACONVERTER_H__ + +#include <grammar/Regular/LeftRG.h> +#include <automaton/FSM/NFA.h> + +namespace rg2fa +{ + +/** + * Converts left regular grammar to finite automaton. + * Source: Melichar 2.102. + */ +class LRGtoFAConverter +{ +public: + /** + * Performs conversion. + * @return FSM equivalent to source grammar. + */ + automaton::NFA convert(const grammar::LeftRG& grammar); +}; + +} /* namespace rg2fa */ + +#endif /* __LRGTOFACONVERTER_H__ */ diff --git a/alib2algo/src/conversions/rg2fa/rrg2fa/RRGtoFAConverter.cpp b/alib2algo/src/conversions/rg2fa/rrg2fa/RRGtoFAConverter.cpp new file mode 100644 index 0000000000..62bdf29d57 --- /dev/null +++ b/alib2algo/src/conversions/rg2fa/rrg2fa/RRGtoFAConverter.cpp @@ -0,0 +1,57 @@ +#include "RRGtoFAConverter.h" + +#include <label/StringLabel.h> +#include <automaton/Automaton.h> +#include <alphabet/LabeledSymbol.h> + +namespace rg2fa +{ + +automaton::NFA RRGtoFAConverter::convert(const grammar::RightRG& grammar) +{ + std::map<alphabet::Symbol, automaton::State> stateMap; + + automaton::NFA automaton; + automaton.setInputSymbols(grammar.getTerminalAlphabet()); + for(const auto& symbol : grammar.getNonterminalAlphabet()) + { + automaton::State state(static_cast<const alphabet::LabeledSymbol&>(symbol.getData()).getLabel()); + automaton.addState(state); + stateMap.insert(std::make_pair(symbol, state)); + } + + const automaton::State AState = automaton::createUniqueState(automaton::State(label::Label(label::StringLabel("A"))), automaton.getStates()); + automaton.addState(AState); + + // step 3, construct \delta + for(const auto& rule : grammar.getRules()) + { + const alphabet::Symbol& lhs = rule.first; + for(const auto& ruleRHS : rule.second) + { + if(ruleRHS.is<std::pair<alphabet::Symbol, alphabet::Symbol>>()) // if B->aC => \delta(B,a)=C + { + const std::pair<alphabet::Symbol, alphabet::Symbol>& rhs = ruleRHS.get<std::pair<alphabet::Symbol, alphabet::Symbol>>(); + automaton.addTransition(stateMap.find(lhs)->second, rhs.first, stateMap.find(rhs.second)->second); + } + else // if B->a => \delta(B,a)=AState + { + const alphabet::Symbol& rhs = ruleRHS.get<alphabet::Symbol>(); + automaton.addTransition(stateMap.find(lhs)->second, rhs, AState); + } + } + } + + // step 4 + automaton.addInitialState(stateMap.find(grammar.getInitialSymbol())->second); + + // step 5 + automaton.addFinalState(AState); + if(grammar.getGeneratesEpsilon()) + for(const auto& state : automaton.getInitialStates()) + automaton.addFinalState(state); + + return automaton; +} + +} /* namespace conversions */ diff --git a/alib2algo/src/conversions/rg2fa/rrg2fa/RRGtoFAConverter.h b/alib2algo/src/conversions/rg2fa/rrg2fa/RRGtoFAConverter.h new file mode 100644 index 0000000000..30666e4cfe --- /dev/null +++ b/alib2algo/src/conversions/rg2fa/rrg2fa/RRGtoFAConverter.h @@ -0,0 +1,26 @@ +#ifndef __RRGTOFACONVERTER_H__ +#define __RRGTOFACONVERTER_H__ + +#include <grammar/Regular/RightRG.h> +#include <automaton/FSM/NFA.h> + +namespace rg2fa +{ + +/** + * Converts left regular grammar to finite automaton. + * Source: Melichar 2.98 + */ +class RRGtoFAConverter +{ +public: + /** + * Performs conversion. + * @return FSM equivalent to source grammar. + */ + automaton::NFA convert(const grammar::RightRG& grammar); +}; + +} /* namespace rg2fa */ + +#endif /* __RRGTOFACONVERTER_H__ */ -- GitLab