From 4f62bf89a9f7147deb3370cdb7b1041c0bf7c0d1 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Sun, 18 Dec 2016 22:07:07 +0100
Subject: [PATCH] template some more algorithms

---
 .../transform/AutomatonIteration.cpp          | 38 ----------
 .../automaton/transform/AutomatonIteration.h  | 45 ++++++++++-
 .../AutomatonIterationEpsilonTransition.cpp   | 18 +----
 .../AutomatonIterationEpsilonTransition.h     | 20 ++++-
 .../src/automaton/transform/Compaction.cpp    | 66 +----------------
 .../src/automaton/transform/Compaction.h      | 74 ++++++++++++++++++-
 6 files changed, 134 insertions(+), 127 deletions(-)

diff --git a/alib2algo/src/automaton/transform/AutomatonIteration.cpp b/alib2algo/src/automaton/transform/AutomatonIteration.cpp
index b298142286..c079d65a95 100644
--- a/alib2algo/src/automaton/transform/AutomatonIteration.cpp
+++ b/alib2algo/src/automaton/transform/AutomatonIteration.cpp
@@ -16,45 +16,7 @@ automaton::Automaton AutomatonIteration::iteration(const automaton::Automaton& a
 	return dispatch(automaton.getData());
 }
 
-automaton::NFA < > AutomatonIteration::iteration(const automaton::DFA < > & automaton) {
-	automaton::NFA < > res(automaton);
-
-	for(const auto& qf : res.getFinalStates())
-		for(const auto& t : res.getTransitionsToState(qf))
-			res.addTransition(t.first.first, t.first.second, res.getInitialState());
-
-	label::Label newInitialState = common::createUnique(automaton.getInitialState(), automaton.getStates());
-	res.addState(newInitialState);
-	res.setInitialState(newInitialState);
-	res.addFinalState(newInitialState);
-
-	for(const auto& t : automaton.getTransitionsFromState(automaton.getInitialState()))
-		res.addTransition(newInitialState, t.first.second, t.second);
-
-	return res;
-}
-
 auto AutomatonIterationDFA = AutomatonIteration::RegistratorWrapper < automaton::NFA < >, automaton::DFA < > > ( AutomatonIteration::iteration );
-
-automaton::NFA < > AutomatonIteration::iteration(const automaton::NFA < > & automaton) {
-	automaton::NFA < > res(automaton);
-
-	for(const auto& qf : res.getFinalStates())
-		for(const auto& t : res.getTransitionsToState(qf))
-			res.addTransition(t.first.first, t.first.second, res.getInitialState());
-
-	label::Label newInitialState = common::createUnique(automaton.getInitialState(), automaton.getStates());
-	res.addState(newInitialState);
-	res.setInitialState(newInitialState);
-	res.addFinalState(newInitialState);
-
-	for(const auto& t : automaton.getTransitionsFromState(automaton.getInitialState()))
-		for (const label::Label & toState : t.second )
-			res.addTransition(newInitialState, t.first.second, toState);
-
-	return res;
-}
-
 auto AutomatonIterationNFA = AutomatonIteration::RegistratorWrapper < automaton::NFA < >, automaton::NFA < > > (AutomatonIteration::iteration);
 
 } /* namespace transform */
diff --git a/alib2algo/src/automaton/transform/AutomatonIteration.h b/alib2algo/src/automaton/transform/AutomatonIteration.h
index e05ef2e1f6..813ad6aadb 100644
--- a/alib2algo/src/automaton/transform/AutomatonIteration.h
+++ b/alib2algo/src/automaton/transform/AutomatonIteration.h
@@ -24,10 +24,51 @@ class AutomatonIteration : public std::SingleDispatch<AutomatonIteration, automa
 public:
 	static automaton::Automaton iteration(const automaton::Automaton& automaton);
 
-	static automaton::NFA < > iteration(const automaton::DFA < > & automaton);
-	static automaton::NFA < > iteration(const automaton::NFA < > & automaton);
+	template < class SymbolType, class StateType >
+	static automaton::NFA < SymbolType, StateType > iteration(const automaton::DFA < SymbolType, StateType > & automaton);
+	template < class SymbolType, class StateType >
+	static automaton::NFA < SymbolType, StateType > iteration(const automaton::NFA < SymbolType, StateType > & automaton);
 };
 
+template < class SymbolType, class StateType >
+automaton::NFA < SymbolType, StateType > AutomatonIteration::iteration(const automaton::DFA < SymbolType, StateType > & automaton) {
+	automaton::NFA < SymbolType, StateType > res(automaton);
+
+	for(const auto& qf : res.getFinalStates())
+		for(const auto& t : res.getTransitionsToState(qf))
+			res.addTransition(t.first.first, t.first.second, res.getInitialState());
+
+	StateType newInitialState = common::createUnique(automaton.getInitialState(), automaton.getStates());
+	res.addState(newInitialState);
+	res.setInitialState(newInitialState);
+	res.addFinalState(newInitialState);
+
+	for(const auto& t : automaton.getTransitionsFromState(automaton.getInitialState()))
+		res.addTransition(newInitialState, t.first.second, t.second);
+
+	return res;
+}
+
+template < class SymbolType, class StateType >
+automaton::NFA < SymbolType, StateType > AutomatonIteration::iteration(const automaton::NFA < SymbolType, StateType > & automaton) {
+	automaton::NFA < SymbolType, StateType > res(automaton);
+
+	for(const auto& qf : res.getFinalStates())
+		for(const auto& t : res.getTransitionsToState(qf))
+			res.addTransition(t.first.first, t.first.second, res.getInitialState());
+
+	StateType newInitialState = common::createUnique(automaton.getInitialState(), automaton.getStates());
+	res.addState(newInitialState);
+	res.setInitialState(newInitialState);
+	res.addFinalState(newInitialState);
+
+	for(const auto& t : automaton.getTransitionsFromState(automaton.getInitialState()))
+		for (const label::Label & toState : t.second )
+			res.addTransition(newInitialState, t.first.second, toState);
+
+	return res;
+}
+
 } /* namespace transform */
 
 } /* namespace automaton */
diff --git a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
index c0a49d1f1b..67d92430ae 100644
--- a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
+++ b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
@@ -16,23 +16,7 @@ automaton::Automaton AutomatonIterationEpsilonTransition::iteration(const automa
 	return dispatch(automaton.getData());
 }
 
-template<class T>
-automaton::EpsilonNFA < > AutomatonIterationEpsilonTransition::iteration(const T& automaton) {
-	automaton::EpsilonNFA < > res(automaton);
-
-	for(const auto&q : automaton.getFinalStates())
-		res.addTransition(q, automaton.getInitialState());
-
-	label::Label newInitialState = common::createUnique(automaton.getInitialState(), automaton.getStates());
-	res.addState(newInitialState);
-	res.setInitialState(newInitialState);
-	res.addFinalState(newInitialState);
-
-	res.addTransition(newInitialState, automaton.getInitialState());
-	return res;
-}
-
-auto AutomatonIterationEpsilonTransitionDFA = AutomatonIterationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::DFA<>>(AutomatonIterationEpsilonTransition::iteration);
+auto AutomatonIterationEpsilonTransitionDFA = AutomatonIterationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::DFA < > >(AutomatonIterationEpsilonTransition::iteration);
 auto AutomatonIterationEpsilonTransitionNFA = AutomatonIterationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::NFA < > >(AutomatonIterationEpsilonTransition::iteration);
 auto AutomatonIterationEpsilonTransitionEpsilonNFA = AutomatonIterationEpsilonTransition::RegistratorWrapper<automaton::EpsilonNFA < >, automaton::EpsilonNFA < > >(AutomatonIterationEpsilonTransition::iteration);
 
diff --git a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h
index adfe609d41..7615e25e1e 100644
--- a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h
+++ b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h
@@ -24,10 +24,26 @@ class AutomatonIterationEpsilonTransition : public std::SingleDispatch<Automaton
 public:
 	static automaton::Automaton iteration(const automaton::Automaton& automaton);
 
-	template<class T>
-	static automaton::EpsilonNFA < > iteration(const T& automaton);
+	template < class T, class SymbolType = typename automaton::SymbolTypeOfAutomaton < T >, class EpsilonType = DefaultEpsilonType, class StateType = typename automaton::StateTypeOfAutomaton < T > >
+	static automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > iteration(const T& automaton);
 };
 
+template < class T, class SymbolType, class EpsilonType, class StateType >
+automaton::EpsilonNFA < SymbolType, EpsilonType, StateType > AutomatonIterationEpsilonTransition::iteration(const T& automaton) {
+	automaton::EpsilonNFA < > res(automaton);
+
+	for(const auto&q : automaton.getFinalStates())
+		res.addTransition(q, automaton.getInitialState());
+
+	StateType newInitialState = common::createUnique(automaton.getInitialState(), automaton.getStates());
+	res.addState(newInitialState);
+	res.setInitialState(newInitialState);
+	res.addFinalState(newInitialState);
+
+	res.addTransition(newInitialState, automaton.getInitialState());
+	return res;
+}
+
 } /* namespace transform */
 
 } /* namespace automaton */
diff --git a/alib2algo/src/automaton/transform/Compaction.cpp b/alib2algo/src/automaton/transform/Compaction.cpp
index 43417fa743..32e58355f5 100644
--- a/alib2algo/src/automaton/transform/Compaction.cpp
+++ b/alib2algo/src/automaton/transform/Compaction.cpp
@@ -7,12 +7,6 @@
 
 #include "Compaction.h"
 
-#include <automaton/FSM/CompactNFA.h>
-#include <automaton/FSM/DFA.h>
-
-#include <stack>
-#include <tuple>
-
 namespace automaton {
 
 namespace transform {
@@ -21,66 +15,8 @@ automaton::Automaton Compaction::convert(const automaton::Automaton& automaton)
 	return dispatch(automaton.getData());
 }
 
-automaton::CompactNFA < > Compaction::convert(const automaton::CompactNFA < > & automaton) {
-	return automaton;
-}
-
 auto CompactionCompactNFA = Compaction::RegistratorWrapper<automaton::CompactNFA < >, automaton::CompactNFA < > >(Compaction::convert);
-
-automaton::CompactNFA < > Compaction::convert(const automaton::DFA<>& automaton) {
-	automaton::CompactNFA < > res(automaton.getInitialState());
-	res.setInputAlphabet(automaton.getInputAlphabet());
-
-	std::set<label::Label> visited;
-
-	std::stack<std::tuple<label::Label, label::Label, alphabet::Symbol>> stack; // state x lastFork x symbol we used to go to that state
-	for(const auto& transition: automaton.getTransitionsFromState(automaton.getInitialState()))
-		stack.push(std::make_tuple(transition.second, automaton.getInitialState(), transition.first.second));
-
-	if(automaton.getFinalStates().count(automaton.getInitialState()) > 0)
-		res.addFinalState(automaton.getInitialState());
-
-	while(!stack.empty()) {
-		label::Label q = std::move(std::get<0>(stack.top()));
-		label::Label lastFork = std::move(std::get<1>(stack.top()));
-		alphabet::Symbol symbol = std::move(std::get<2>(stack.top()));
-		stack.pop();
-
-		std::vector < alphabet::Symbol > path { symbol };
-
-		std::map<std::pair<label::Label, alphabet::Symbol>, label::Label> transitions;
-		// only 1 child and nonfinal
-		while((transitions = automaton.getTransitionsFromState(q)).size() == 1 && automaton.getFinalStates().count(q) == 0) {
-			const std::pair<std::pair<label::Label, alphabet::Symbol>, label::Label>& transition = * transitions.begin();
-			path.push_back(transition.first.second);
-			q = transition.second;
-		}
-
-		// fork or final state
-		res.addState(q);
-
-		if(automaton.getFinalStates().count(q))
-			res.addFinalState(q);
-
-		res.addTransition(lastFork, path, q);
-
-		for(const std::pair<const std::pair<label::Label, alphabet::Symbol>, label::Label>& transition : automaton.getTransitionsFromState(q))
-			if(visited.insert(transition.second).second)
-				stack.push(std::make_tuple(transition.second, q, transition.first.second));
-
-	}
-
-	return res;
-}
-
-auto CompactionDFA = Compaction::RegistratorWrapper<automaton::CompactNFA < >, automaton::DFA<>>(Compaction::convert);
-
-automaton::CompactNFA < > Compaction::convert(const automaton::NFA < > & automaton) {
-	automaton::CompactNFA < > res(automaton.getInitialState());
-	// TODO
-	return res;
-}
-
+auto CompactionDFA = Compaction::RegistratorWrapper<automaton::CompactNFA < >, automaton::DFA < > >(Compaction::convert);
 auto CompactionNFA = Compaction::RegistratorWrapper<automaton::CompactNFA < >, automaton::NFA < > >(Compaction::convert);
 
 } /* namespace transform */
diff --git a/alib2algo/src/automaton/transform/Compaction.h b/alib2algo/src/automaton/transform/Compaction.h
index 76a99b994a..b9543cc154 100644
--- a/alib2algo/src/automaton/transform/Compaction.h
+++ b/alib2algo/src/automaton/transform/Compaction.h
@@ -8,9 +8,15 @@
 #ifndef COMPACTION_H_
 #define COMPACTION_H_
 
+#include <stack>
+#include <tuple>
+
 #include <core/multipleDispatch.hpp>
+
 #include "automaton/Automaton.h"
 #include "automaton/AutomatonFeatures.h"
+#include <automaton/FSM/CompactNFA.h>
+#include <automaton/FSM/DFA.h>
 
 namespace automaton {
 
@@ -21,9 +27,12 @@ namespace transform {
  */
 class Compaction : public std::SingleDispatch<Compaction, automaton::Automaton, const automaton::AutomatonBase &> {
 public:
-	static automaton::CompactNFA < > convert( const automaton::DFA<>& automaton);
-	static automaton::CompactNFA < > convert( const automaton::NFA < > & automaton);
-	static automaton::CompactNFA < > convert( const automaton::CompactNFA < > & automaton);
+	template < class SymbolType, class StateType >
+	static automaton::CompactNFA < SymbolType, StateType > convert( const automaton::DFA < SymbolType, StateType > & automaton);
+	template < class SymbolType, class StateType >
+	static automaton::CompactNFA < SymbolType, StateType > convert( const automaton::NFA < SymbolType, StateType > & automaton);
+	template < class SymbolType, class StateType >
+	static automaton::CompactNFA < SymbolType, StateType > convert( const automaton::CompactNFA < SymbolType, StateType > & automaton);
 
 	/**
 	 * Transforms
@@ -33,6 +42,65 @@ public:
 	static automaton::Automaton convert( const automaton::Automaton & automaton );
 };
 
+template < class SymbolType, class StateType >
+automaton::CompactNFA < SymbolType, StateType > Compaction::convert(const automaton::CompactNFA < SymbolType, StateType > & automaton) {
+	return automaton;
+}
+
+template < class SymbolType, class StateType >
+automaton::CompactNFA < SymbolType, StateType > Compaction::convert(const automaton::DFA < SymbolType, StateType > & automaton) {
+	automaton::CompactNFA < SymbolType, StateType > res(automaton.getInitialState());
+	res.setInputAlphabet(automaton.getInputAlphabet());
+
+	std::set<label::Label> visited;
+
+	std::stack<std::tuple<label::Label, label::Label, alphabet::Symbol>> stack; // state x lastFork x symbol we used to go to that state
+	for(const auto& transition: automaton.getTransitionsFromState(automaton.getInitialState()))
+		stack.push(std::make_tuple(transition.second, automaton.getInitialState(), transition.first.second));
+
+	if(automaton.getFinalStates().count(automaton.getInitialState()) > 0)
+		res.addFinalState(automaton.getInitialState());
+
+	while(!stack.empty()) {
+		label::Label q = std::move(std::get<0>(stack.top()));
+		label::Label lastFork = std::move(std::get<1>(stack.top()));
+		alphabet::Symbol symbol = std::move(std::get<2>(stack.top()));
+		stack.pop();
+
+		std::vector < alphabet::Symbol > path { symbol };
+
+		std::map<std::pair<label::Label, alphabet::Symbol>, label::Label> transitions;
+		// only 1 child and nonfinal
+		while((transitions = automaton.getTransitionsFromState(q)).size() == 1 && automaton.getFinalStates().count(q) == 0) {
+			const std::pair<std::pair<label::Label, alphabet::Symbol>, label::Label>& transition = * transitions.begin();
+			path.push_back(transition.first.second);
+			q = transition.second;
+		}
+
+		// fork or final state
+		res.addState(q);
+
+		if(automaton.getFinalStates().count(q))
+			res.addFinalState(q);
+
+		res.addTransition(lastFork, path, q);
+
+		for(const std::pair<const std::pair<label::Label, alphabet::Symbol>, label::Label>& transition : automaton.getTransitionsFromState(q))
+			if(visited.insert(transition.second).second)
+				stack.push(std::make_tuple(transition.second, q, transition.first.second));
+
+	}
+
+	return res;
+}
+
+template < class SymbolType, class StateType >
+automaton::CompactNFA < SymbolType, StateType > Compaction::convert(const automaton::NFA < SymbolType, StateType > & automaton) {
+	automaton::CompactNFA < SymbolType, StateType > res(automaton.getInitialState());
+	// TODO
+	return res;
+}
+
 } /* namespace transform */
 
 } /* namespace automaton */
-- 
GitLab