From 50c88b572cbe436df77051600f40492e43bade66 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Tue, 20 Dec 2016 17:11:13 +0100
Subject: [PATCH] template AllEpsilonClosure

---
 .../efficient/AllEpsilonClosure.cpp           | 146 +---------------
 .../properties/efficient/AllEpsilonClosure.h  | 158 +++++++++++++++++-
 2 files changed, 156 insertions(+), 148 deletions(-)

diff --git a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp
index ac6e066589..0966da9435 100644
--- a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp
+++ b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.cpp
@@ -7,152 +7,20 @@
 
 #include "AllEpsilonClosure.h"
 
-#include <automaton/FSM/ExtendedNFA.h>
-#include <automaton/FSM/CompactNFA.h>
-#include <automaton/FSM/EpsilonNFA.h>
-#include <automaton/FSM/MultiInitialStateNFA.h>
-#include <automaton/FSM/NFA.h>
-#include <automaton/FSM/DFA.h>
-
-#include <set>
-#include <map>
-#include <iostream>
-
-#include <regexp/properties/RegExpEpsilon.h>
-
 namespace automaton {
 
 namespace properties {
 
 namespace efficient {
 
-void process(const std::map<label::Label, std::set<label::Label>>& epsilonTransitions, const label::Label * state, std::map<label::Label, std::set<label::Label>>& closures, std::set<label::Label>& visited, std::set<label::Label>& nonvisited) {
-	if(visited.count(*state)) return;
-
-	state = &*visited.insert(*state).first;
-	nonvisited.erase(*state);
-
-	auto tos = epsilonTransitions.find(*state);
-	if(tos == epsilonTransitions.end()) return;
-
-	for(const label::Label& to : tos->second) {
-		process(epsilonTransitions, &to, closures, visited, nonvisited);
-		closures[*state].insert(closures[to].begin(), closures[to].end());
-	}
-}
-
-std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::EpsilonNFA < > & fsm) {
-	std::map<label::Label, std::set<label::Label>> res;
-
-	for(const label::Label& state : fsm.getStates())
-		res[state].insert(state);
-
-	std::set<label::Label> visited;
-	std::set<label::Label> nonvisited = fsm.getStates();
-
-	std::map<label::Label, std::set<label::Label>> epsilonTransitions = fsm.getEpsilonTransitions();
-
-	while(nonvisited.size()) {
-		process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited);
-	}
-
-	// to correctly handle epsilon loops (swap visited and nonvisited)
-
-	while(visited.size()) {
-		process(epsilonTransitions, &*visited.begin(), res, nonvisited, visited);
-	}
-
-	return res;
-}
-
-auto AllEpsilonClosureEpsilonNFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::EpsilonNFA < > >(AllEpsilonClosure::allEpsilonClosure);
-
-std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::MultiInitialStateNFA < > & fsm) {
-	std::map<label::Label, std::set<label::Label>> closure;
-	for(const label::Label& state : fsm.getStates())
-		closure[state].insert(state);
-	return closure;
-}
-
-auto AllEpsilonClosureMultiInitialStateNFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::MultiInitialStateNFA < >>(AllEpsilonClosure::allEpsilonClosure);
-
-std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::NFA < > & fsm) {
-	std::map<label::Label, std::set<label::Label>> closure;
-	for(const label::Label& state : fsm.getStates())
-		closure[state].insert(state);
-	return closure;
-}
-
-auto AllEpsilonClosureNFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::NFA < > >(AllEpsilonClosure::allEpsilonClosure);
-
-std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::DFA < > & fsm) {
-	std::map<label::Label, std::set<label::Label>> closure;
-	for(const label::Label& state : fsm.getStates())
-		closure[state].insert(state);
-	return closure;
-}
-
-auto AllEpsilonClosureDFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::DFA<>>(AllEpsilonClosure::allEpsilonClosure);
-
-std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::ExtendedNFA < > & fsm) {
-	std::map<label::Label, std::set<label::Label>> res;
-
-	for(const label::Label& state : fsm.getStates())
-		res[state].insert(state);
-
-	std::set<label::Label> visited;
-	std::set<label::Label> nonvisited = fsm.getStates();
-
-	std::map<label::Label, std::set<label::Label>> epsilonTransitions;
-	for(const std::pair<const std::pair<label::Label, regexp::UnboundedRegExpStructure < alphabet::Symbol > >, std::set<label::Label> >& transition : fsm.getTransitions() )
-		if( regexp::properties::RegExpEpsilon::languageContainsEpsilon( transition.first.second ) )
-			epsilonTransitions[transition.first.first].insert(transition.second.begin(), transition.second.end());
-
-	while(nonvisited.size()) {
-		process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited);
-	}
-
-	// to correctly handle epsilon loops (swap visited and nonvisited)
-
-	while(visited.size()) {
-		process(epsilonTransitions, &*visited.begin(), res, nonvisited, visited);
-	}
-
-	return res;
-}
-
-auto AllEpsilonClosureExtendedNFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::ExtendedNFA < > >(AllEpsilonClosure::allEpsilonClosure);
-
-std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure( const automaton::CompactNFA < > & fsm) {
-	std::map<label::Label, std::set<label::Label>> res;
-
-	for(const label::Label& state : fsm.getStates())
-		res[state].insert(state);
-
-	std::set<label::Label> visited;
-	std::set<label::Label> nonvisited = fsm.getStates();
-
-	std::map<label::Label, std::set<label::Label>> epsilonTransitions;
-	for(const std::pair<const std::pair<label::Label, std::vector < alphabet::Symbol > >, std::set<label::Label> >& transition : fsm.getTransitions() )
-		if( transition.first.second.size() == 0 )
-			epsilonTransitions[transition.first.first].insert(transition.second.begin(), transition.second.end());
-
-	while(nonvisited.size()) {
-		process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited);
-	}
-
-	// to correctly handle epsilon loops (swap visited and nonvisited)
-
-	while(visited.size()) {
-		process(epsilonTransitions, &*visited.begin(), res, nonvisited, visited);
-	}
-
-	return res;
-}
-
-auto AllEpsilonClosureCompactNFA = AllEpsilonClosure::RegistratorWrapper<std::map<label::Label, std::set<label::Label>>, automaton::CompactNFA < > >(AllEpsilonClosure::allEpsilonClosure);
+auto AllEpsilonClosureEpsilonNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::EpsilonNFA < > >(AllEpsilonClosure::allEpsilonClosure);
+auto AllEpsilonClosureMultiInitialStateNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::MultiInitialStateNFA < >>(AllEpsilonClosure::allEpsilonClosure);
+auto AllEpsilonClosureNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::NFA < > >(AllEpsilonClosure::allEpsilonClosure);
+auto AllEpsilonClosureDFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::DFA<>>(AllEpsilonClosure::allEpsilonClosure);
+auto AllEpsilonClosureExtendedNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::ExtendedNFA < > >(AllEpsilonClosure::allEpsilonClosure);
+auto AllEpsilonClosureCompactNFA = AllEpsilonClosure::RegistratorWrapper<std::map<DefaultStateType, std::set<DefaultStateType>>, automaton::CompactNFA < > >(AllEpsilonClosure::allEpsilonClosure);
 
-std::map<label::Label, std::set<label::Label>> AllEpsilonClosure::allEpsilonClosure(const Automaton& automaton) {
+std::map<DefaultStateType, std::set<DefaultStateType>> AllEpsilonClosure::allEpsilonClosure(const Automaton& automaton) {
 	return dispatch(automaton.getData());
 }
 
diff --git a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h
index a0e51e4af1..6168f8ea0f 100644
--- a/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h
+++ b/alib2elgo/src/automaton/properties/efficient/AllEpsilonClosure.h
@@ -15,7 +15,18 @@
 #include "automaton/Automaton.h"
 #include "automaton/AutomatonFeatures.h"
 
-#include <label/Label.h>
+#include <automaton/FSM/ExtendedNFA.h>
+#include <automaton/FSM/CompactNFA.h>
+#include <automaton/FSM/EpsilonNFA.h>
+#include <automaton/FSM/MultiInitialStateNFA.h>
+#include <automaton/FSM/NFA.h>
+#include <automaton/FSM/DFA.h>
+
+#include <set>
+#include <map>
+#include <iostream>
+
+#include <regexp/properties/RegExpEpsilon.h>
 
 namespace automaton {
 
@@ -23,21 +34,150 @@ namespace properties {
 
 namespace efficient {
 
-class AllEpsilonClosure : public std::SingleDispatch<AllEpsilonClosure, std::map<label::Label, std::set<label::Label>>, const automaton::AutomatonBase &> {
+class AllEpsilonClosure : public std::SingleDispatch<AllEpsilonClosure, std::map<DefaultStateType, std::set<DefaultStateType>>, const automaton::AutomatonBase &> {
+	template < class StateType >
+	static void process(const std::map<StateType, std::set<StateType>>& epsilonTransitions, const StateType * state, std::map<StateType, std::set<StateType>>& closures, std::set<StateType>& visited, std::set<StateType>& nonvisited);
 public:
-	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::Automaton & automaton);
+	static std::map<DefaultStateType, std::set<DefaultStateType>> allEpsilonClosure( const automaton::Automaton & automaton);
 
 	/**
 	 * Computes allEpsilon closure of a state in allEpsilon nonfree automaton
 	 */
-	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::EpsilonNFA < > & fsm);
-	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::MultiInitialStateNFA < > & fsm);
-	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::NFA < > & fsm);
-	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::DFA < > & fsm);
-	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::ExtendedNFA < > & fsm);
-	static std::map<label::Label, std::set<label::Label>> allEpsilonClosure( const automaton::CompactNFA < > & fsm);
+	template < class SymbolType, class EpsilonType, class StateType >
+	static std::map<StateType, std::set<StateType>> allEpsilonClosure( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm);
+	template < class SymbolType, class StateType >
+	static std::map<StateType, std::set<StateType>> allEpsilonClosure( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm);
+	template < class SymbolType, class StateType >
+	static std::map<StateType, std::set<StateType>> allEpsilonClosure( const automaton::NFA < SymbolType, StateType > & fsm);
+	template < class SymbolType, class StateType >
+	static std::map<StateType, std::set<StateType>> allEpsilonClosure( const automaton::DFA < SymbolType, StateType > & fsm);
+	template < class SymbolType, class StateType >
+	static std::map<StateType, std::set<StateType>> allEpsilonClosure( const automaton::ExtendedNFA < SymbolType, StateType > & fsm);
+	template < class SymbolType, class StateType >
+	static std::map<StateType, std::set<StateType>> allEpsilonClosure( const automaton::CompactNFA < SymbolType, StateType > & fsm);
 };
 
+template < class StateType >
+void AllEpsilonClosure::process(const std::map<StateType, std::set<StateType>>& epsilonTransitions, const StateType * state, std::map<StateType, std::set<StateType>>& closures, std::set<StateType>& visited, std::set<StateType>& nonvisited) {
+	if(visited.count(*state)) return;
+
+	state = &*visited.insert(*state).first;
+	nonvisited.erase(*state);
+
+	auto tos = epsilonTransitions.find(*state);
+	if(tos == epsilonTransitions.end()) return;
+
+	for(const StateType& to : tos->second) {
+		process(epsilonTransitions, &to, closures, visited, nonvisited);
+		closures[*state].insert(closures[to].begin(), closures[to].end());
+	}
+}
+
+template < class SymbolType, class EpsilonType, class StateType >
+std::map<StateType, std::set<StateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > & fsm) {
+	std::map<StateType, std::set<StateType>> res;
+
+	for(const StateType& state : fsm.getStates())
+		res[state].insert(state);
+
+	std::set<StateType> visited;
+	std::set<StateType> nonvisited = fsm.getStates();
+
+	std::map<StateType, std::set<StateType>> epsilonTransitions = fsm.getEpsilonTransitions();
+
+	while(nonvisited.size()) {
+		process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited);
+	}
+
+	// to correctly handle epsilon loops (swap visited and nonvisited)
+
+	while(visited.size()) {
+		process(epsilonTransitions, &*visited.begin(), res, nonvisited, visited);
+	}
+
+	return res;
+}
+
+template < class SymbolType, class StateType >
+std::map<StateType, std::set<StateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm) {
+	std::map<StateType, std::set<StateType>> closure;
+	for(const StateType& state : fsm.getStates())
+		closure[state].insert(state);
+	return closure;
+}
+
+template < class SymbolType, class StateType >
+std::map<StateType, std::set<StateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::NFA < SymbolType, StateType > & fsm) {
+	std::map<StateType, std::set<StateType>> closure;
+	for(const StateType& state : fsm.getStates())
+		closure[state].insert(state);
+	return closure;
+}
+
+template < class SymbolType, class StateType >
+std::map<StateType, std::set<StateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::DFA < SymbolType, StateType > & fsm) {
+	std::map<StateType, std::set<StateType>> closure;
+	for(const StateType& state : fsm.getStates())
+		closure[state].insert(state);
+	return closure;
+}
+
+template < class SymbolType, class StateType >
+std::map<StateType, std::set<StateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::ExtendedNFA < SymbolType, StateType > & fsm) {
+	std::map<StateType, std::set<StateType>> res;
+
+	for(const StateType& state : fsm.getStates())
+		res[state].insert(state);
+
+	std::set<StateType> visited;
+	std::set<StateType> nonvisited = fsm.getStates();
+
+	std::map<StateType, std::set<StateType>> epsilonTransitions;
+	for(const std::pair<const std::pair<StateType, regexp::UnboundedRegExpStructure < SymbolType > >, std::set<StateType> >& transition : fsm.getTransitions() )
+		if( regexp::properties::RegExpEpsilon::languageContainsEpsilon( transition.first.second ) )
+			epsilonTransitions[transition.first.first].insert(transition.second.begin(), transition.second.end());
+
+	while(nonvisited.size()) {
+		process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited);
+	}
+
+	// to correctly handle epsilon loops (swap visited and nonvisited)
+
+	while(visited.size()) {
+		process(epsilonTransitions, &*visited.begin(), res, nonvisited, visited);
+	}
+
+	return res;
+}
+
+template < class SymbolType, class StateType >
+std::map<StateType, std::set<StateType>> AllEpsilonClosure::allEpsilonClosure( const automaton::CompactNFA < SymbolType, StateType > & fsm) {
+	std::map<StateType, std::set<StateType>> res;
+
+	for(const StateType& state : fsm.getStates())
+		res[state].insert(state);
+
+	std::set<StateType> visited;
+	std::set<StateType> nonvisited = fsm.getStates();
+
+	std::map<StateType, std::set<StateType>> epsilonTransitions;
+	for(const std::pair<const std::pair<StateType, std::vector < SymbolType > >, std::set<StateType> >& transition : fsm.getTransitions() )
+		if( transition.first.second.size() == 0 )
+			epsilonTransitions[transition.first.first].insert(transition.second.begin(), transition.second.end());
+
+	while(nonvisited.size()) {
+		process(epsilonTransitions, &*nonvisited.begin(), res, visited, nonvisited);
+	}
+
+	// to correctly handle epsilon loops (swap visited and nonvisited)
+
+	while(visited.size()) {
+		process(epsilonTransitions, &*visited.begin(), res, nonvisited, visited);
+	}
+
+	return res;
+}
+
 } /* namespace efficient */
 
 } /* namespace properties */
-- 
GitLab