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