From 10de8dd25273717be996a58533e1860d778d7b67 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Wed, 25 Apr 2018 09:05:12 +0200
Subject: [PATCH] implement run of Epsilon NFA

---
 alib2algo/src/automaton/run/Accept.cpp    |  1 +
 alib2algo/src/automaton/run/Accept.h      | 11 +++++
 alib2algo/src/automaton/run/Occurrences.h |  1 -
 alib2algo/src/automaton/run/Run.h         | 55 +++++++++++++++++++++++
 4 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/alib2algo/src/automaton/run/Accept.cpp b/alib2algo/src/automaton/run/Accept.cpp
index b1bd895e5e..725e85f854 100644
--- a/alib2algo/src/automaton/run/Accept.cpp
+++ b/alib2algo/src/automaton/run/Accept.cpp
@@ -14,6 +14,7 @@ namespace run {
 
 auto AcceptDFALinearString = registration::AbstractRegister < Accept, bool, const automaton::DFA < > &, const string::LinearString < > & > ( Accept::accept );
 auto AcceptNFALinearString = registration::AbstractRegister < Accept, bool, const automaton::NFA < > &, const string::LinearString < > & > ( Accept::accept );
+auto AcceptEpsilonNFALinearString = registration::AbstractRegister < Accept, bool, const automaton::EpsilonNFA < > &, const string::LinearString < > & > ( Accept::accept );
 auto AcceptDFTARankedTree = registration::AbstractRegister < Accept, bool, const automaton::DFTA < > &, const tree::RankedTree < > & > ( Accept::accept );
 auto AcceptNFTARankedTree = registration::AbstractRegister < Accept, bool, const automaton::NFTA < > &, const tree::RankedTree < > & > ( Accept::accept );
 auto AcceptInputDrivenDPDALinearString = registration::AbstractRegister < Accept, bool, const automaton::InputDrivenDPDA < > &, const string::LinearString < > & > ( Accept::accept );
diff --git a/alib2algo/src/automaton/run/Accept.h b/alib2algo/src/automaton/run/Accept.h
index c4f2a150a3..7651184918 100644
--- a/alib2algo/src/automaton/run/Accept.h
+++ b/alib2algo/src/automaton/run/Accept.h
@@ -40,6 +40,8 @@ public:
 	static bool accept ( const automaton::DFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
 	template < class SymbolType, class StateType >
 	static bool accept ( const automaton::NFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static bool accept ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string );
 	template < class SymbolType, class RankType, class StateType >
 	static bool accept ( const automaton::DFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree );
 	template < class SymbolType, class RankType, class StateType >
@@ -73,6 +75,15 @@ bool Accept::accept ( const automaton::NFA < SymbolType, StateType > & automaton
 			} );
 }
 
+template < class SymbolType, class EpsilonType, class StateType >
+bool Accept::accept ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	ext::tuple < bool, ext::set < StateType >, ext::set < unsigned > > res = Run::calculateStates ( automaton, string );
+
+	return std::get < 0 > ( res ) && std::any_of ( std::get < 1 > ( res ).begin ( ), std::get < 1 > ( res ).end ( ), [&] ( const StateType & state ) {
+				return automaton.getFinalStates ( ).count ( state );
+			} );
+}
+
 template < class SymbolType, class RankType, class StateType >
 bool Accept::accept ( const automaton::DFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree ) {
 	ext::tuple < bool, StateType, ext::set < unsigned > > res = Run::calculateState ( automaton, tree );
diff --git a/alib2algo/src/automaton/run/Occurrences.h b/alib2algo/src/automaton/run/Occurrences.h
index 5a3b7ad42c..29243e3579 100644
--- a/alib2algo/src/automaton/run/Occurrences.h
+++ b/alib2algo/src/automaton/run/Occurrences.h
@@ -13,7 +13,6 @@
 
 #include "Run.h"
 #include <automaton/FSM/DFA.h>
-#include <automaton/FSM/NFA.h>
 #include <automaton/TA/DFTA.h>
 #include <automaton/PDA/InputDrivenDPDA.h>
 #include <automaton/PDA/VisiblyPushdownDPDA.h>
diff --git a/alib2algo/src/automaton/run/Run.h b/alib2algo/src/automaton/run/Run.h
index 9ecd196378..d292f1a03b 100644
--- a/alib2algo/src/automaton/run/Run.h
+++ b/alib2algo/src/automaton/run/Run.h
@@ -13,6 +13,7 @@
 
 #include <automaton/FSM/DFA.h>
 #include <automaton/FSM/NFA.h>
+#include <automaton/FSM/EpsilonNFA.h>
 #include <automaton/TA/DFTA.h>
 #include <automaton/TA/NFTA.h>
 #include <automaton/PDA/InputDrivenDPDA.h>
@@ -28,6 +29,8 @@
 #include <alib/algorithm>
 #include <alib/iterator>
 
+#include <automaton/properties/EpsilonClosure.h>
+
 namespace automaton {
 
 namespace run {
@@ -45,6 +48,8 @@ public:
 	static ext::tuple < bool, StateType, ext::set < unsigned > > calculateState ( const automaton::DFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
 	template < class SymbolType, class StateType >
 	static ext::tuple < bool, ext::set < StateType >, ext::set < unsigned > > calculateStates ( const automaton::NFA < SymbolType, StateType > & automaton, const string::LinearString < SymbolType > & string );
+	template < class SymbolType, class EpsilonType, class StateType >
+	static ext::tuple < bool, ext::set < StateType >, ext::set < unsigned > > calculateStates ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string );
 	template < class SymbolType, class RankType, class StateType >
 	static ext::tuple < bool, StateType, ext::set < unsigned > > calculateState ( const automaton::DFTA < SymbolType, RankType, StateType > & automaton, const tree::RankedTree < SymbolType, RankType > & tree );
 	template < class SymbolType, class RankType, class StateType >
@@ -142,6 +147,56 @@ ext::tuple < bool, ext::set < StateType >, ext::set < unsigned > > Run::calculat
 
 // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
+template < class SymbolType, class EpsilonType, class StateType >
+ext::tuple < bool, ext::set < StateType >, ext::set < unsigned > > Run::calculateStates ( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & automaton, const string::LinearString < SymbolType > & string ) {
+	bool res = true;
+	unsigned i = 0;
+	ext::set < unsigned > occurrences;
+	ext::set < StateType > states {
+		automaton.getInitialState ( )
+	};
+
+	for ( const StateType & state : states )
+		if ( automaton.getFinalStates ( ).count ( state ) )
+			occurrences.insert ( i );
+
+	if ( common::GlobalData::verbose )
+		common::Streams::log << states << std::endl;
+
+	for ( const SymbolType & symbol : string.getContent ( ) ) {
+		ext::set < StateType > next;
+
+		for ( const StateType & state : states ) {
+			auto transitions = automaton.getTransitions ( ).find ( ext::make_pair ( state, ext::variant < EpsilonType, SymbolType > ( symbol ) ) );
+
+			if ( transitions == automaton.getTransitions ( ).end ( ) ) continue;
+
+			next.insert ( transitions->second.begin ( ), transitions->second.end ( ) );
+		}
+
+		ext::set < StateType > epsilonNext;
+
+		for ( const StateType & state : next ) {
+			const ext::set < StateType > closure = automaton::properties::EpsilonClosure::epsilonClosure ( automaton, state );
+			epsilonNext.insert ( closure.begin ( ), closure.end ( ) );
+		}
+
+		i++;
+		states = epsilonNext;
+
+		for ( const StateType & state : states )
+			if ( automaton.getFinalStates ( ).count ( state ) )
+				occurrences.insert ( i );
+
+		if ( common::GlobalData::verbose )
+			common::Streams::log << states << std::endl;
+	}
+
+	return ext::make_tuple ( res, states, occurrences );
+}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
 template < class SymbolType, class RankType, class StateType >
 ext::pair < bool, StateType > Run::calculateState ( const automaton::DFTA < SymbolType, RankType, StateType > & automaton, const ext::tree < common::ranked_symbol < SymbolType, RankType > > & node, ext::set < unsigned > & occ, unsigned & i ) {
 	ext::vector < StateType > states;
-- 
GitLab