From bf30589a38a288bd0f46b39e9f021d4c1bb2cb18 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Fri, 5 Sep 2014 19:12:23 +0200 Subject: [PATCH] support more concrete formalisms --- aconversions2/src/ConversionHandler.cpp | 19 +++-- adeterminize2/src/adeterminize.cpp | 2 + .../conversions/fa2re/BrzozowskiAlgebraic.cpp | 68 ++++++++++++----- .../conversions/fa2re/BrzozowskiAlgebraic.h | 17 +---- alib2algo/test-src/play/playTest.cpp | 6 +- examples2/automaton/aconversion.test.22.xml | 76 +++++++++++++++++++ 6 files changed, 144 insertions(+), 44 deletions(-) create mode 100644 examples2/automaton/aconversion.test.22.xml diff --git a/aconversions2/src/ConversionHandler.cpp b/aconversions2/src/ConversionHandler.cpp index d97f20a16e..9f40da9e86 100644 --- a/aconversions2/src/ConversionHandler.cpp +++ b/aconversions2/src/ConversionHandler.cpp @@ -104,14 +104,21 @@ void ConversionHandler::convertRG( void ) void ConversionHandler::convertFSMtoRE( void ) { - const automaton::NFA fsm = alib::DataFactory::fromTokens<automaton::NFA>( m_tokens ); - switch( m_algorithm ) { case BRZOZOWSKI_ALGEBRAIC: { - fa2re::BrzozowskiAlgebraic conv( fsm ); - regexp::UnboundedRegExp re = conv.convert(); - alib::DataFactory::toStdout(re); + std::string xmlMark = m_tokens.front( ).getData( ); + if( xmlMark == "NFA") { + const automaton::NFA fsm = alib::DataFactory::fromTokens<automaton::NFA>( m_tokens ); + regexp::UnboundedRegExp re = fa2re::BrzozowskiAlgebraic::convert( fsm ); + alib::DataFactory::toStdout(re); + } else if( xmlMark == "DFA") { + const automaton::DFA fsm = alib::DataFactory::fromTokens<automaton::DFA>( m_tokens ); + regexp::UnboundedRegExp re = fa2re::BrzozowskiAlgebraic::convert( fsm ); + alib::DataFactory::toStdout(re); + } else { + throw exception::AlibException("Unrecognised formalism"); + } break; } case STATE_ELIMINATION: @@ -386,7 +393,7 @@ ConversionHandler::TFormalism ConversionHandler::parseFormalismFromTokens( void { std::string xmlMark = m_tokens.front( ).getData( ); - if( xmlMark == "automaton" || xmlMark == "NFA" ) + if( xmlMark == "automaton" || xmlMark == "NFA" || xmlMark == "DFA" ) return FINITE_AUTOMATON; if( xmlMark == "regexp" || xmlMark == "unboundedRegexp" ) diff --git a/adeterminize2/src/adeterminize.cpp b/adeterminize2/src/adeterminize.cpp index 0a920ed23f..7f11fe1488 100644 --- a/adeterminize2/src/adeterminize.cpp +++ b/adeterminize2/src/adeterminize.cpp @@ -110,6 +110,8 @@ int main(int argc, char** argv) { automaton::DFA automaton = alib::DataFactory::fromTokens<automaton::DFA>(tokens); alib::DataFactory::toStdout(automaton); return 0; + } else { + throw exception::AlibException("Unsupported formalism"); } } diff --git a/alib2algo/src/conversions/fa2re/BrzozowskiAlgebraic.cpp b/alib2algo/src/conversions/fa2re/BrzozowskiAlgebraic.cpp index 3cee454517..1b7db735b5 100644 --- a/alib2algo/src/conversions/fa2re/BrzozowskiAlgebraic.cpp +++ b/alib2algo/src/conversions/fa2re/BrzozowskiAlgebraic.cpp @@ -7,6 +7,8 @@ #include "BrzozowskiAlgebraic.h" #include "alphabet/Symbol.h" +#include "automaton/FSM/DFA.h" +#include "automaton/FSM/NFA.h" using namespace alib; using namespace automaton; @@ -15,41 +17,32 @@ using namespace regexp; namespace fa2re { -BrzozowskiAlgebraic::BrzozowskiAlgebraic( const automaton::NFA & automaton ) : m_automaton( automaton ) -{ - -} - -BrzozowskiAlgebraic::~BrzozowskiAlgebraic( void ) -{ - -} - -regexp::UnboundedRegExp BrzozowskiAlgebraic::convert( void ) +template<> +regexp::UnboundedRegExp BrzozowskiAlgebraic::convert( const automaton::NFA & automaton ) { equations::RightRegularEquationSolver solver; // initialize equations - for( const auto & q : m_automaton.getStates( ) ) + for( const auto & q : automaton.getStates( ) ) solver.addSymbol( alphabet::Symbol( alphabet::LabeledSymbol( q.getName( ) ) ) ); - for( const auto & q : m_automaton.getStates( ) ) + for( const auto & q : automaton.getStates( ) ) { - if( isInSet( q, m_automaton.getFinalStates( ) ) ) + if( isInSet( q, automaton.getFinalStates( ) ) ) solver.addEquation( alphabet::Symbol( alphabet::LabeledSymbol ( q.getName( ) ) ), new regexp::UnboundedRegExpEpsilon( ) ); else solver.addEquation( alphabet::Symbol( alphabet::LabeledSymbol ( q.getName( ) ) ), new regexp::UnboundedRegExpEmpty( ) ); } - for( const auto & p : m_automaton.getStates( ) ) + for( const auto & p : automaton.getStates( ) ) { - for( const auto & q : m_automaton.getStates( ) ) + for( const auto & q : automaton.getStates( ) ) { regexp::UnboundedRegExpAlternation* alt = new regexp::UnboundedRegExpAlternation( ); alt->appendElement( regexp::UnboundedRegExpEmpty { } ); - for( const auto & symbol : m_automaton.getInputAlphabet( ) ) { - auto toStates = m_automaton.getTransitionsFromState(p)[std::make_pair(p, symbol)]; + for( const auto & symbol : automaton.getInputAlphabet( ) ) { + auto toStates = automaton.getTransitionsFromState(p)[std::make_pair(p, symbol)]; if ( isInSet( q , toStates ) ) alt->appendElement( regexp::UnboundedRegExpSymbol { symbol } ); } @@ -58,7 +51,7 @@ regexp::UnboundedRegExp BrzozowskiAlgebraic::convert( void ) } regexp::UnboundedRegExpAlternation alternation; - for(const auto& initialSymbol : m_automaton.getInitialStates() ) { + for(const auto& initialSymbol : automaton.getInitialStates() ) { // set symbol for which the solver will solve equation system alphabet::Symbol tmp( alphabet::LabeledSymbol ( initialSymbol.getName( ) ) ); @@ -68,4 +61,41 @@ regexp::UnboundedRegExp BrzozowskiAlgebraic::convert( void ) return regexp::UnboundedRegExp { alternation }; } +template<> +regexp::UnboundedRegExp BrzozowskiAlgebraic::convert( const automaton::DFA & automaton ) +{ + equations::RightRegularEquationSolver solver; + + // initialize equations + for( const auto & q : automaton.getStates( ) ) + solver.addSymbol( alphabet::Symbol( alphabet::LabeledSymbol( q.getName( ) ) ) ); + + for( const auto & q : automaton.getStates( ) ) + { + if( isInSet( q, automaton.getFinalStates( ) ) ) + solver.addEquation( alphabet::Symbol( alphabet::LabeledSymbol ( q.getName( ) ) ), new regexp::UnboundedRegExpEpsilon( ) ); + else + solver.addEquation( alphabet::Symbol( alphabet::LabeledSymbol ( q.getName( ) ) ), new regexp::UnboundedRegExpEmpty( ) ); + } + + for( const auto & p : automaton.getStates( ) ) + { + for( const auto & q : automaton.getStates( ) ) + { + regexp::UnboundedRegExpAlternation* alt = new regexp::UnboundedRegExpAlternation( ); + alt->appendElement( regexp::UnboundedRegExpEmpty { } ); + + for( const auto & symbol : automaton.getInputAlphabet( ) ) { + auto toState = automaton.getTransitionsFromState(p); + if( isKeyInMap(std::make_pair(p, symbol), toState) && toState.find(std::make_pair(p, symbol))->second == q ) + alt->appendElement( regexp::UnboundedRegExpSymbol { symbol } ); + } + solver.addEquation( alphabet::Symbol( alphabet::LabeledSymbol ( p.getName( ) ) ), alphabet::Symbol( alphabet::LabeledSymbol( q.getName( ) ) ), alt ); + } + } + + return regexp::UnboundedRegExp { solver.solve( alphabet::Symbol( alphabet::LabeledSymbol (automaton.getInitialState().getName() ) ) ).getRegExp() }; +} + + } /* namespace fa2re */ diff --git a/alib2algo/src/conversions/fa2re/BrzozowskiAlgebraic.h b/alib2algo/src/conversions/fa2re/BrzozowskiAlgebraic.h index 4f83815847..3bba605629 100644 --- a/alib2algo/src/conversions/fa2re/BrzozowskiAlgebraic.h +++ b/alib2algo/src/conversions/fa2re/BrzozowskiAlgebraic.h @@ -13,7 +13,6 @@ #include <queue> #include <regexp/unbounded/UnboundedRegExpElements.h> -#include <automaton/FSM/NFA.h> #include "common/macros.h" #include "../../equations/RightRegularEquationSolver.h" @@ -31,24 +30,12 @@ namespace fa2re class BrzozowskiAlgebraic { public: - /** - * @param fsm Source automaton - */ - BrzozowskiAlgebraic( const automaton::NFA & fsm ); - - ~BrzozowskiAlgebraic( void ); - /** * Performs conversion. * @return regular expression equivalent to input automaton. */ - regexp::UnboundedRegExp convert( void ); - -private: - /** - * Input automaton - */ - const automaton::NFA & m_automaton; + template <class T> + static regexp::UnboundedRegExp convert( const T & automaton ); }; } /* namespace fa2re */ diff --git a/alib2algo/test-src/play/playTest.cpp b/alib2algo/test-src/play/playTest.cpp index 32a9088766..0fcfdacefb 100644 --- a/alib2algo/test-src/play/playTest.cpp +++ b/alib2algo/test-src/play/playTest.cpp @@ -33,8 +33,7 @@ void playTest::testPlay() { automaton::NFA nfa1 = glushkov1.convert(); - fa2re::BrzozowskiAlgebraic brzozowski(nfa1); - regexp::UnboundedRegExp regexp2( static_cast<const regexp::UnboundedRegExp &>( brzozowski.convert() ) ); + regexp::UnboundedRegExp regexp2( static_cast<const regexp::UnboundedRegExp &>( fa2re::BrzozowskiAlgebraic::convert(nfa1) ) ); re2fa::Glushkov glushkov2(regexp2); automaton::NFA nfa2 = glushkov2.convert(); @@ -45,7 +44,6 @@ void playTest::testPlay() { automaton::DFA mdfa1 = minimize::MinimizeDFA::minimize(dfa1); automaton::DFA mdfa2 = minimize::MinimizeDFA::minimize(dfa2); - std::cout << mdfa1 << std::endl; - std::cout << mdfa2 << std::endl; + CPPUNIT_ASSERT( mdfa1 == mdfa2); } } diff --git a/examples2/automaton/aconversion.test.22.xml b/examples2/automaton/aconversion.test.22.xml new file mode 100644 index 0000000000..695efe96c2 --- /dev/null +++ b/examples2/automaton/aconversion.test.22.xml @@ -0,0 +1,76 @@ +<NFA> + <states> + <StringLabel>0</StringLabel> + <StringLabel>1</StringLabel> + <StringLabel>2</StringLabel> + <StringLabel>3</StringLabel> + <StringLabel>4</StringLabel> + <StringLabel>5</StringLabel> + </states> + <inputAlphabet> + <LabeledSymbol><CharacterLabel>a</CharacterLabel></LabeledSymbol> + <LabeledSymbol><CharacterLabel>b</CharacterLabel></LabeledSymbol> + <LabeledSymbol><CharacterLabel>c</CharacterLabel></LabeledSymbol> + </inputAlphabet> + <initialStates> + <StringLabel>0</StringLabel> + </initialStates> + <finalStates> + <StringLabel>1</StringLabel> + <StringLabel>3</StringLabel> + <StringLabel>4</StringLabel> + <StringLabel>5</StringLabel> + </finalStates> + <transitions> + <transition> + <from><StringLabel>0</StringLabel></from> + <input><LabeledSymbol><CharacterLabel>a</CharacterLabel></LabeledSymbol></input> + <to><StringLabel>1</StringLabel></to> + </transition> + <transition> + <from><StringLabel>0</StringLabel></from> + <input><LabeledSymbol><CharacterLabel>b</CharacterLabel></LabeledSymbol></input> + <to><StringLabel>2</StringLabel></to> + </transition> + <transition> + <from><StringLabel>1</StringLabel></from> + <input><LabeledSymbol><CharacterLabel>a</CharacterLabel></LabeledSymbol></input> + <to><StringLabel>3</StringLabel></to> + </transition> + <transition> + <from><StringLabel>1</StringLabel></from> + <input><LabeledSymbol><CharacterLabel>b</CharacterLabel></LabeledSymbol></input> + <to><StringLabel>4</StringLabel></to> + </transition> + <transition> + <from><StringLabel>1</StringLabel></from> + <input><LabeledSymbol><CharacterLabel>c</CharacterLabel></LabeledSymbol></input> + <to><StringLabel>3</StringLabel></to> + </transition> + <transition> + <from><StringLabel>2</StringLabel></from> + <input><LabeledSymbol><CharacterLabel>a</CharacterLabel></LabeledSymbol></input> + <to><StringLabel>5</StringLabel></to> + </transition> + <transition> + <from><StringLabel>2</StringLabel></from> + <input><LabeledSymbol><CharacterLabel>b</CharacterLabel></LabeledSymbol></input> + <to><StringLabel>2</StringLabel></to> + </transition> + <transition> + <from><StringLabel>4</StringLabel></from> + <input><LabeledSymbol><CharacterLabel>a</CharacterLabel></LabeledSymbol></input> + <to><StringLabel>3</StringLabel></to> + </transition> + <transition> + <from><StringLabel>4</StringLabel></from> + <input><LabeledSymbol><CharacterLabel>b</CharacterLabel></LabeledSymbol></input> + <to><StringLabel>4</StringLabel></to> + </transition> + <transition> + <from><StringLabel>5</StringLabel></from> + <input><LabeledSymbol><CharacterLabel>b</CharacterLabel></LabeledSymbol></input> + <to><StringLabel>5</StringLabel></to> + </transition> + </transitions> +</NFA> -- GitLab