From 7136b31e0034bec729d18893f9b290084245a1c4 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Wed, 21 Dec 2016 11:02:55 +0100
Subject: [PATCH] finish templating elgo algorithms

---
 .../properties/efficient/ReachableStates.cpp  | 92 ++-----------------
 .../properties/efficient/ReachableStates.h    | 86 ++++++++++++++++-
 .../properties/efficient/UsefullStates.cpp    | 70 ++------------
 .../properties/efficient/UsefullStates.h      | 63 ++++++++++++-
 .../automaton/simplify/efficient/trimTest.cpp | 22 ++---
 5 files changed, 164 insertions(+), 169 deletions(-)

diff --git a/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp b/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp
index 9fb30fc6b1..b634efafda 100644
--- a/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp
+++ b/alib2elgo/src/automaton/properties/efficient/ReachableStates.cpp
@@ -7,100 +7,22 @@
 
 #include "ReachableStates.h"
 
-#include <automaton/FSM/ExtendedNFA.h>
-#include <automaton/FSM/CompactNFA.h>
-#include <automaton/FSM/EpsilonNFA.h>
-#include <automaton/FSM/NFA.h>
-#include <automaton/FSM/DFA.h>
-
-#include <set>
-#include <map>
-#include <queue>
-
 namespace automaton {
 
 namespace properties {
 
 namespace efficient {
 
-std::set<label::Label> ReachableStates::reachableStates(const Automaton& automaton) {
+std::set<DefaultStateType> ReachableStates::reachableStates(const Automaton& automaton) {
 	return dispatch(automaton.getData());
 }
 
-template<class T>
-std::set<label::Label> ReachableStates::reachableStates( const T & fsm ) {
-	std::map<label::Label, std::set<label::Label>> transitions;
-	for(const auto& transition : fsm.getTransitions())
-		transitions[transition.first.first].insert(transition.second.begin(), transition.second.end());
-
-	std::deque<label::Label> queue { fsm.getInitialState( ) };
-	std::set<label::Label> visited { fsm.getInitialState( ) };
-
-	while( !queue.empty() ) {
-		const std::set<label::Label>& to = transitions[queue.front()];
-		queue.pop_front();
-
-		for(const label::Label& process : to)
-			if(visited.insert(process).second) {
-				queue.push_back(std::move(const_cast<label::Label&>(process)));
-			}
-	}
-
-	return visited;
-}
-
-auto ReachableStatesEpsilonNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::EpsilonNFA < > >(ReachableStates::reachableStates);
-auto ReachableStatesNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::NFA < > >(ReachableStates::reachableStates);
-auto ReachableStatesCompactNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::CompactNFA < > >(ReachableStates::reachableStates);
-auto ReachableStatesExtendedNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::ExtendedNFA < > >(ReachableStates::reachableStates);
-
-template<>
-std::set<label::Label> ReachableStates::reachableStates( const automaton::MultiInitialStateNFA < > & fsm ) {
-	std::map<label::Label, std::set<label::Label>> transitions;
-	for(const auto& transition : fsm.getTransitions())
-		transitions[transition.first.first].insert(transition.second.begin(), transition.second.end());
-
-	std::deque<label::Label> queue ( fsm.getInitialStates( ).begin(), fsm.getInitialStates().end() );
-	std::set<label::Label> visited = fsm.getInitialStates( );
-
-	while( !queue.empty() ) {
-		const std::set<label::Label>& to = transitions[queue.front()];
-		queue.pop_front();
-
-		for(const label::Label& process : to)
-			if(visited.insert(process).second) {
-				queue.push_back(std::move(const_cast<label::Label&>(process)));
-			}
-	}
-
-	return visited;
-}
-
-auto ReachableStatesMultiInitialStateNFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::MultiInitialStateNFA < >>(ReachableStates::reachableStates);
-
-template<>
-std::set<label::Label> ReachableStates::reachableStates( const automaton::DFA < > & fsm ) {
-	std::map<label::Label, std::set<label::Label>> transitions;
-	for(const auto& transition : fsm.getTransitions())
-		transitions[transition.first.first].insert(transition.second);
-
-	std::deque<label::Label> queue { fsm.getInitialState( ) };
-	std::set<label::Label> visited { fsm.getInitialState( ) };
-
-	while( !queue.empty() ) {
-		const std::set<label::Label>& to = transitions[queue.front()];
-		queue.pop_front();
-
-		for(const label::Label& process : to)
-			if(visited.insert(process).second) {
-				queue.push_back(std::move(const_cast<label::Label&>(process)));
-			}
-	}
-
-	return visited;
-}
-
-auto ReachableStatesDFA = ReachableStates::RegistratorWrapper<std::set<label::Label>, automaton::DFA<>>(ReachableStates::reachableStates);
+auto ReachableStatesEpsilonNFA = ReachableStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::EpsilonNFA < > >(ReachableStates::reachableStates);
+auto ReachableStatesNFA = ReachableStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::NFA < > >(ReachableStates::reachableStates);
+auto ReachableStatesCompactNFA = ReachableStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::CompactNFA < > >(ReachableStates::reachableStates);
+auto ReachableStatesExtendedNFA = ReachableStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::ExtendedNFA < > >(ReachableStates::reachableStates);
+auto ReachableStatesMultiInitialStateNFA = ReachableStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::MultiInitialStateNFA < >>(ReachableStates::reachableStates);
+auto ReachableStatesDFA = ReachableStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::DFA < > >(ReachableStates::reachableStates);
 
 } /* namespace efficient */
 
diff --git a/alib2elgo/src/automaton/properties/efficient/ReachableStates.h b/alib2elgo/src/automaton/properties/efficient/ReachableStates.h
index 006b6c1fa3..6113170771 100644
--- a/alib2elgo/src/automaton/properties/efficient/ReachableStates.h
+++ b/alib2elgo/src/automaton/properties/efficient/ReachableStates.h
@@ -12,11 +12,17 @@
 #include <algorithm>
 #include <deque>
 #include <set>
+#include <map>
+#include <queue>
 
 #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/NFA.h>
+#include <automaton/FSM/DFA.h>
 
 namespace automaton {
 
@@ -24,17 +30,87 @@ namespace properties {
 
 namespace efficient {
 
-class ReachableStates : public std::SingleDispatch<ReachableStates, std::set<label::Label>, const automaton::AutomatonBase &> {
+class ReachableStates : public std::SingleDispatch<ReachableStates, std::set<DefaultStateType>, const automaton::AutomatonBase &> {
 public:
-	static std::set<label::Label> reachableStates( const automaton::Automaton & automaton );
+	static std::set<DefaultStateType> reachableStates( const automaton::Automaton & automaton );
 
 	/**
 	 * Removes dead states from FSM. Melichar 2.29
 	 */
-	template<class T>
-	static std::set<label::Label> reachableStates( const T & fsm );
+	template < class T, class SymbolType = typename automaton::SymbolTypeOfAutomaton < T >, class StateType = typename automaton::StateTypeOfAutomaton < T > >
+	static std::set<StateType> reachableStates( const T & fsm );
+	template < class SymbolType, class StateType >
+	static std::set<StateType> reachableStates( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm );
+	template < class SymbolType, class StateType >
+	static std::set<StateType> reachableStates( const automaton::DFA < SymbolType, StateType > & fsm );
 };
 
+template < class T, class SymbolType, class StateType >
+std::set<StateType> ReachableStates::reachableStates( const T & fsm ) {
+	std::map<StateType, std::set<StateType>> transitions;
+	for(const auto& transition : fsm.getTransitions())
+		transitions[transition.first.first].insert(transition.second.begin(), transition.second.end());
+
+	std::deque<StateType> queue { fsm.getInitialState( ) };
+	std::set<StateType> visited { fsm.getInitialState( ) };
+
+	while( !queue.empty() ) {
+		const std::set<StateType>& to = transitions[queue.front()];
+		queue.pop_front();
+
+		for(const StateType& process : to)
+			if(visited.insert(process).second) {
+				queue.push_back(std::move(const_cast<StateType&>(process)));
+			}
+	}
+
+	return visited;
+}
+
+template < class SymbolType, class StateType >
+std::set<StateType> ReachableStates::reachableStates( const automaton::MultiInitialStateNFA < SymbolType, StateType > & fsm ) {
+	std::map<StateType, std::set<StateType>> transitions;
+	for(const auto& transition : fsm.getTransitions())
+		transitions[transition.first.first].insert(transition.second.begin(), transition.second.end());
+
+	std::deque<StateType> queue ( fsm.getInitialStates( ).begin(), fsm.getInitialStates().end() );
+	std::set<StateType> visited = fsm.getInitialStates( );
+
+	while( !queue.empty() ) {
+		const std::set<StateType>& to = transitions[queue.front()];
+		queue.pop_front();
+
+		for(const StateType& process : to)
+			if(visited.insert(process).second) {
+				queue.push_back(std::move(const_cast<StateType&>(process)));
+			}
+	}
+
+	return visited;
+}
+
+template < class SymbolType, class StateType >
+std::set<StateType> ReachableStates::reachableStates( const automaton::DFA < SymbolType, StateType > & fsm ) {
+	std::map<StateType, std::set<StateType>> transitions;
+	for(const auto& transition : fsm.getTransitions())
+		transitions[transition.first.first].insert(transition.second);
+
+	std::deque<StateType> queue { fsm.getInitialState( ) };
+	std::set<StateType> visited { fsm.getInitialState( ) };
+
+	while( !queue.empty() ) {
+		const std::set<StateType>& to = transitions[queue.front()];
+		queue.pop_front();
+
+		for(const StateType& process : to)
+			if(visited.insert(process).second) {
+				queue.push_back(std::move(const_cast<StateType&>(process)));
+			}
+	}
+
+	return visited;
+}
+
 } /* namespace efficient */
 
 } /* namespace properties */
diff --git a/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp b/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp
index 4804bd174c..5c5db127c9 100644
--- a/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp
+++ b/alib2elgo/src/automaton/properties/efficient/UsefullStates.cpp
@@ -7,78 +7,22 @@
 
 #include "UsefullStates.h"
 
-#include <automaton/FSM/ExtendedNFA.h>
-#include <automaton/FSM/CompactNFA.h>
-#include <automaton/FSM/EpsilonNFA.h>
-#include <automaton/FSM/NFA.h>
-#include <automaton/FSM/DFA.h>
-
-#include <set>
-#include <map>
-#include <queue>
-
 namespace automaton {
 
 namespace properties {
 
 namespace efficient {
 
-std::set<label::Label> UsefullStates::usefullStates(const Automaton& automaton) {
+std::set<DefaultStateType> UsefullStates::usefullStates(const Automaton& automaton) {
 	return dispatch(automaton.getData());
 }
 
-template<class T>
-std::set<label::Label> UsefullStates::usefullStates( const T & fsm ) {
-	std::map<label::Label, std::set<label::Label>> reversedTransitions;
-	for(const auto& transition : fsm.getTransitions())
-		for(const label::Label& to : transition.second)
-			reversedTransitions[to].insert(transition.first.first);
-
-	std::deque<label::Label> queue ( fsm.getFinalStates( ).begin(), fsm.getFinalStates().end() );
-	std::set<label::Label> visited = fsm.getFinalStates( );
-
-	while( !queue.empty() ) {
-		const std::set<label::Label>& to = reversedTransitions[queue.front()];
-		queue.pop_front();
-
-		for(const label::Label& process : to)
-			if(visited.insert(process).second) {
-				queue.push_back(std::move(const_cast<label::Label&>(process)));
-			}
-	}
-
-	return visited;
-}
-
-auto UsefullStatesEpsilonNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::EpsilonNFA < > >(UsefullStates::usefullStates);
-auto UsefullStatesNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::NFA < > >(UsefullStates::usefullStates);
-auto UsefullStatesCompactNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::CompactNFA < > >(UsefullStates::usefullStates);
-auto UsefullStatesExtendedNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::ExtendedNFA < > >(UsefullStates::usefullStates);
-auto UsefullStatesMultiInitialStateNFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::MultiInitialStateNFA < >>(UsefullStates::usefullStates);
-
-template<>
-std::set<label::Label> UsefullStates::usefullStates( const automaton::DFA < > & fsm ) {
-	std::map<label::Label, std::set<label::Label>> reversedTransitions;
-	for(const auto& transition : fsm.getTransitions())
-		reversedTransitions[transition.second].insert(transition.first.first);
-
-	std::deque<label::Label> queue ( fsm.getFinalStates( ).begin(), fsm.getFinalStates().end() );
-	std::set<label::Label> visited = fsm.getFinalStates( );
-
-	while( !queue.empty() ) {
-		const std::set<label::Label>& to = reversedTransitions[queue.front()];
-		queue.pop_front();
-
-		for(const label::Label& process : to)
-			if(visited.insert(process).second) {
-				queue.push_back(std::move(const_cast<label::Label&>(process)));
-			}
-	}
-
-	return visited;
-}
-
-auto UsefullStatesDFA = UsefullStates::RegistratorWrapper<std::set<label::Label>, automaton::DFA<>>(UsefullStates::usefullStates);
+auto UsefullStatesEpsilonNFA = UsefullStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::EpsilonNFA < > >(UsefullStates::usefullStates);
+auto UsefullStatesNFA = UsefullStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::NFA < > >(UsefullStates::usefullStates);
+auto UsefullStatesCompactNFA = UsefullStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::CompactNFA < > >(UsefullStates::usefullStates);
+auto UsefullStatesExtendedNFA = UsefullStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::ExtendedNFA < > >(UsefullStates::usefullStates);
+auto UsefullStatesMultiInitialStateNFA = UsefullStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::MultiInitialStateNFA < >>(UsefullStates::usefullStates);
+auto UsefullStatesDFA = UsefullStates::RegistratorWrapper<std::set<DefaultStateType>, automaton::DFA < > >(UsefullStates::usefullStates);
 
 } /* namespace efficient */
 
diff --git a/alib2elgo/src/automaton/properties/efficient/UsefullStates.h b/alib2elgo/src/automaton/properties/efficient/UsefullStates.h
index 4067b441d9..8710c3934f 100644
--- a/alib2elgo/src/automaton/properties/efficient/UsefullStates.h
+++ b/alib2elgo/src/automaton/properties/efficient/UsefullStates.h
@@ -12,11 +12,17 @@
 #include <algorithm>
 #include <deque>
 #include <set>
+#include <map>
+#include <queue>
 
 #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/NFA.h>
+#include <automaton/FSM/DFA.h>
 
 namespace automaton {
 
@@ -24,17 +30,64 @@ namespace properties {
 
 namespace efficient {
 
-class UsefullStates : public std::SingleDispatch<UsefullStates, std::set<label::Label>, const automaton::AutomatonBase &> {
+class UsefullStates : public std::SingleDispatch<UsefullStates, std::set<DefaultStateType>, const automaton::AutomatonBase &> {
 public:
-	static std::set<label::Label> usefullStates( const automaton::Automaton & automaton );
+	static std::set<DefaultStateType> usefullStates( const automaton::Automaton & automaton );
 
 	/**
 	 * Removes dead states from FSM. Melichar 2.32
 	 */
-	template<class T>
-	static std::set<label::Label> usefullStates( const T & fsm );
+	template < class T, class SymbolType = typename automaton::SymbolTypeOfAutomaton < T >, class StateType = typename automaton::StateTypeOfAutomaton < T > >
+	static std::set<StateType> usefullStates( const T & fsm );
+	template < class SymbolType, class StateType >
+	static std::set<StateType> usefullStates( const automaton::DFA < SymbolType, StateType > & fsm );
 };
 
+template < class T, class SymbolType, class StateType >
+std::set<StateType> UsefullStates::usefullStates( const T & fsm ) {
+	std::map<StateType, std::set<StateType>> reversedTransitions;
+	for(const auto& transition : fsm.getTransitions())
+		for(const StateType& to : transition.second)
+			reversedTransitions[to].insert(transition.first.first);
+
+	std::deque<StateType> queue ( fsm.getFinalStates( ).begin(), fsm.getFinalStates().end() );
+	std::set<StateType> visited = fsm.getFinalStates( );
+
+	while( !queue.empty() ) {
+		const std::set<StateType>& to = reversedTransitions[queue.front()];
+		queue.pop_front();
+
+		for(const StateType& process : to)
+			if(visited.insert(process).second) {
+				queue.push_back(std::move(const_cast<StateType&>(process)));
+			}
+	}
+
+	return visited;
+}
+
+template < class SymbolType, class StateType >
+std::set<StateType> UsefullStates::usefullStates( const automaton::DFA < SymbolType, StateType > & fsm ) {
+	std::map<StateType, std::set<StateType>> reversedTransitions;
+	for(const auto& transition : fsm.getTransitions())
+		reversedTransitions[transition.second].insert(transition.first.first);
+
+	std::deque<StateType> queue ( fsm.getFinalStates( ).begin(), fsm.getFinalStates().end() );
+	std::set<StateType> visited = fsm.getFinalStates( );
+
+	while( !queue.empty() ) {
+		const std::set<StateType>& to = reversedTransitions[queue.front()];
+		queue.pop_front();
+
+		for(const StateType& process : to)
+			if(visited.insert(process).second) {
+				queue.push_back(std::move(const_cast<StateType&>(process)));
+			}
+	}
+
+	return visited;
+}
+
 } /* namespace efficient */
 
 } /* namespace properties */
diff --git a/alib2elgo/test-src/automaton/simplify/efficient/trimTest.cpp b/alib2elgo/test-src/automaton/simplify/efficient/trimTest.cpp
index 8efff3d38d..316d2878b8 100644
--- a/alib2elgo/test-src/automaton/simplify/efficient/trimTest.cpp
+++ b/alib2elgo/test-src/automaton/simplify/efficient/trimTest.cpp
@@ -17,21 +17,21 @@ void trimTest::tearDown() {
 }
 
 void trimTest::testTrimAutomaton() {
-	automaton::DFA<> automaton(label::Label(1));
+	automaton::DFA < > automaton(DefaultStateType(1));
 
-	automaton.addState(label::Label(1));
-	automaton.addState(label::Label(2));
-	automaton.addState(label::Label(3));
-	automaton.addInputSymbol(alphabet::Symbol("a"));
-	automaton.addInputSymbol(alphabet::Symbol("b"));
+	automaton.addState(DefaultStateType(1));
+	automaton.addState(DefaultStateType(2));
+	automaton.addState(DefaultStateType(3));
+	automaton.addInputSymbol(DefaultSymbolType("a"));
+	automaton.addInputSymbol(DefaultSymbolType("b"));
 
-	automaton.addTransition(label::Label(1), alphabet::Symbol("a"), label::Label(2));
-	automaton.addTransition(label::Label(2), alphabet::Symbol("b"), label::Label(1));
-	automaton.addTransition(label::Label(3), alphabet::Symbol("b"), label::Label(1));
+	automaton.addTransition(DefaultStateType(1), DefaultSymbolType("a"), DefaultStateType(2));
+	automaton.addTransition(DefaultStateType(2), DefaultSymbolType("b"), DefaultStateType(1));
+	automaton.addTransition(DefaultStateType(3), DefaultSymbolType("b"), DefaultStateType(1));
 
-	automaton.addFinalState(label::Label(1));
+	automaton.addFinalState(DefaultStateType(1));
 
-	automaton::DFA<> trimed = automaton::simplify::Trim::trim(automaton);
+	automaton::DFA < > trimed = automaton::simplify::Trim::trim(automaton);
 
 	CPPUNIT_ASSERT(trimed.getStates().size() == 2);
 }
-- 
GitLab