From 2509b90168eb6591492381e09d59461a7a92967f Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Sun, 7 Sep 2014 20:52:48 +0200 Subject: [PATCH] EpsilonNFA to RE by algebraic method --- .../conversions/fa2re/BrzozowskiAlgebraic.cpp | 36 +++++++ .../test-src/conversions/re2fa/re2faTest.cpp | 95 +++++++++++++++++++ .../test-src/conversions/re2fa/re2faTest.h | 23 +++++ 3 files changed, 154 insertions(+) create mode 100644 alib2algo/test-src/conversions/re2fa/re2faTest.cpp create mode 100644 alib2algo/test-src/conversions/re2fa/re2faTest.h diff --git a/alib2algo/src/conversions/fa2re/BrzozowskiAlgebraic.cpp b/alib2algo/src/conversions/fa2re/BrzozowskiAlgebraic.cpp index f336c3f2a7..c5d06d955a 100644 --- a/alib2algo/src/conversions/fa2re/BrzozowskiAlgebraic.cpp +++ b/alib2algo/src/conversions/fa2re/BrzozowskiAlgebraic.cpp @@ -13,6 +13,42 @@ namespace fa2re { +template<> +regexp::UnboundedRegExp BrzozowskiAlgebraic::convert( const automaton::EpsilonNFA & 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( ) ) ), regexp::UnboundedRegExpEpsilon { } ); + } + + for( const auto & p : automaton.getSymbolTransitions() ) { + for( const auto & q : p.second ) { + solver.addEquation( alphabet::Symbol( alphabet::LabeledSymbol ( p.first.first.getName() ) ), alphabet::Symbol( alphabet::LabeledSymbol( q.getName() ) ), regexp::UnboundedRegExpSymbol { p.first.second } ); + } + } + + for( const auto & p : automaton.getEpsilonTransitions() ) { + for( const auto & q : p.second ) { + solver.addEquation( alphabet::Symbol( alphabet::LabeledSymbol ( p.first.getName() ) ), alphabet::Symbol( alphabet::LabeledSymbol( q.getName() ) ), regexp::UnboundedRegExpEpsilon { } ); + } + } + + regexp::UnboundedRegExpAlternation alternation; + for(const auto& initialSymbol : automaton.getInitialStates() ) { + // set symbol for which the solver will solve equation system + alphabet::Symbol tmp( alphabet::LabeledSymbol ( initialSymbol.getName( ) ) ); + + alternation.appendElement( solver.solve( tmp ).getRegExp() ); + } + + return regexp::UnboundedRegExp { alternation }; +} + template<> regexp::UnboundedRegExp BrzozowskiAlgebraic::convert( const automaton::NFA & automaton ) { equations::RightRegularEquationSolver solver; diff --git a/alib2algo/test-src/conversions/re2fa/re2faTest.cpp b/alib2algo/test-src/conversions/re2fa/re2faTest.cpp new file mode 100644 index 0000000000..23f3376fe3 --- /dev/null +++ b/alib2algo/test-src/conversions/re2fa/re2faTest.cpp @@ -0,0 +1,95 @@ +#include <list> +#include "re2faTest.h" + +#include "conversions/re2fa/Brzozowski.h" +#include "conversions/re2fa/Glushkov.h" +#include "conversions/re2fa/Thompson.h" +#include "conversions/fa2re/BrzozowskiAlgebraic.h" +#include "determinize/nfa/NFADeterminizer.h" +#include "minimize/dfa/MinimizeDFA.h" +#include "epsilon/epsilonNfa/EpsilonNFAEpsilonRemover.h" + +#include "regexp/unbounded/UnboundedRegExp.h" +#include "regexp/RegExpFromStringParser.h" + +#include "automaton/FSM/NFA.h" + +CPPUNIT_TEST_SUITE_REGISTRATION( re2faTest ); + +void re2faTest::setUp() { +} + +void re2faTest::tearDown() { +} + +void re2faTest::testThompson() { + std::string input = "a+a* b*"; + std::stringstream inputs(input); + + regexp::RegExpFromStringParser parser(inputs); + regexp::RegExp regexp1( parser.parseValue() ); + + re2fa::Thompson thompson1; + automaton::EpsilonNFA enfa1 = thompson1.convert(regexp1); + + regexp::RegExp regexp2( fa2re::BrzozowskiAlgebraic::convert(enfa1) ); + + re2fa::Thompson thompson2; + automaton::EpsilonNFA enfa2 = thompson2.convert(regexp2); + + automaton::NFA nfa1 = epsilon::EpsilonNFAEpsilonRemover::remove(enfa1); + automaton::NFA nfa2 = epsilon::EpsilonNFAEpsilonRemover::remove(enfa2); + + automaton::DFA dfa1 = determinize::NFADeterminizer::determinize(nfa1); + automaton::DFA dfa2 = determinize::NFADeterminizer::determinize(nfa2); + + automaton::DFA mdfa1 = minimize::MinimizeDFA::minimize(dfa1); + automaton::DFA mdfa2 = minimize::MinimizeDFA::minimize(dfa2); + + CPPUNIT_ASSERT( mdfa1 == mdfa2); +} + +void re2faTest::testGlushkov() { + std::string input = "a+a* b*"; + std::stringstream inputs(input); + + regexp::RegExpFromStringParser parser(inputs); + regexp::UnboundedRegExp regexp1( static_cast<const regexp::UnboundedRegExp &>( parser.parseValue().getData() ) ); + + re2fa::Glushkov glushkov1; + automaton::NFA nfa1 = glushkov1.convert(regexp1); + + regexp::UnboundedRegExp regexp2( static_cast<const regexp::UnboundedRegExp &>( fa2re::BrzozowskiAlgebraic::convert(nfa1) ) ); + + re2fa::Glushkov glushkov2; + automaton::NFA nfa2 = glushkov2.convert(regexp2); + + automaton::DFA dfa1 = determinize::NFADeterminizer::determinize(nfa1); + automaton::DFA dfa2 = determinize::NFADeterminizer::determinize(nfa2); + + automaton::DFA mdfa1 = minimize::MinimizeDFA::minimize(dfa1); + automaton::DFA mdfa2 = minimize::MinimizeDFA::minimize(dfa2); + + CPPUNIT_ASSERT( mdfa1 == mdfa2); +} + +void re2faTest::testBrzozowski() { + std::string input = "a+a* b*"; + std::stringstream inputs(input); + + regexp::RegExpFromStringParser parser(inputs); + regexp::RegExp regexp1( parser.parseValue() ); + + re2fa::Brzozowski brzozowski1; + automaton::DFA dfa1 = brzozowski1.convert(regexp1); + + regexp::RegExp regexp2( fa2re::BrzozowskiAlgebraic::convert(dfa1) ); + + re2fa::Brzozowski brzozowski2; + automaton::DFA dfa2 = brzozowski2.convert(regexp2); + + automaton::DFA mdfa1 = minimize::MinimizeDFA::minimize(dfa1); + automaton::DFA mdfa2 = minimize::MinimizeDFA::minimize(dfa2); + + CPPUNIT_ASSERT( mdfa1 == mdfa2); +} diff --git a/alib2algo/test-src/conversions/re2fa/re2faTest.h b/alib2algo/test-src/conversions/re2fa/re2faTest.h new file mode 100644 index 0000000000..0f5454813d --- /dev/null +++ b/alib2algo/test-src/conversions/re2fa/re2faTest.h @@ -0,0 +1,23 @@ +#ifndef RG2RG_TEST_H_ +#define RG2RG_TEST_H_ + +#include <cppunit/extensions/HelperMacros.h> + +class re2faTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( re2faTest ); + CPPUNIT_TEST( testThompson ); + CPPUNIT_TEST( testGlushkov ); + CPPUNIT_TEST( testBrzozowski ); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp(); + void tearDown(); + + void testThompson(); + void testGlushkov(); + void testBrzozowski(); +}; + +#endif // RG2RG_TEST_H_ -- GitLab