From b448dc86bae58a95099aa4d4aa002fed996d30e8 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Sun, 7 Apr 2019 21:15:40 +0200
Subject: [PATCH] unify code in automaton rename algo

---
 alib2algo/src/automaton/simplify/Rename.h | 73 ++++++++++-------------
 alib2std/src/extensions/type_traits.hpp   | 26 ++++++++
 2 files changed, 56 insertions(+), 43 deletions(-)

diff --git a/alib2algo/src/automaton/simplify/Rename.h b/alib2algo/src/automaton/simplify/Rename.h
index 195ee09c82..17b0edc5a0 100644
--- a/alib2algo/src/automaton/simplify/Rename.h
+++ b/alib2algo/src/automaton/simplify/Rename.h
@@ -32,6 +32,7 @@
 
 #include <automaton/FSM/DFA.h>
 #include <automaton/FSM/NFA.h>
+#include <automaton/FSM/EpsilonNFA.h>
 #include <automaton/PDA/DPDA.h>
 #include <automaton/PDA/NPDA.h>
 #include <automaton/PDA/InputDrivenDPDA.h>
@@ -52,32 +53,40 @@ namespace simplify {
  * @sa automaton::simplify::Normalize
  */
 class Rename {
-public:
-	/**
-	 * Rename automaton's states.
-	 *
-	 * @tparam SymbolType Type for input symbols
-	 * @tparam StateType Type for states
-	 *
-	 * @param dfa finite automaton to rename
-	 *
-	 * @return @p dfa with renamed states
-	 */
-	template < class SymbolType, class StateType >
-	static automaton::DFA < SymbolType, unsigned > rename ( const automaton::DFA < SymbolType, StateType > & dfa );
+	template < class T >
+	struct DFATra {
+		using type = automaton::DFA < typename T::SymbolType, unsigned >;
+	};
+
+	template < class T >
+	struct NFATra {
+		using type = automaton::NFA < typename T::SymbolType, unsigned >;
+	};
+
+	template < class T >
+	struct EpsilonNFATra {
+		using type = automaton::EpsilonNFA < typename T::SymbolType, typename T::EpsilonType, unsigned >;
+	};
+
+	template < class T >
+	using RenamedAutomaton = typename ext::casional <
+			ext::boolean < isDFA < T > >, DFATra < T >,
+			ext::boolean < isNFA < T > >, NFATra < T >,
+			ext::boolean < isEpsilonNFA < T > >, EpsilonNFATra < T >
+		>::type::type;
 
+public:
 	/**
 	 * Rename automaton's states.
 	 *
-	 * @tparam SymbolType Type for input symbols
-	 * @tparam StateType Type for states
+	 * @tparam T Type of automaton to rename
 	 *
 	 * @param nfa finite automaton to rename
 	 *
 	 * @return @p dfa with renamed states
 	 */
-	template < class SymbolType, class StateType >
-	static automaton::NFA < SymbolType, unsigned > rename ( const automaton::NFA < SymbolType, StateType > & nfa );
+	template < class T >
+	static ext::require < isDFA < T > || isNFA < T >, Rename::RenamedAutomaton < T > > rename ( const T & fsm );
 
 	/**
 	 * @overload
@@ -174,39 +183,17 @@ public:
 	static automaton::RealTimeHeightDeterministicDPDA < InputSymbolType, EpsilonType, unsigned, unsigned > rename ( const automaton::RealTimeHeightDeterministicDPDA < InputSymbolType, EpsilonType, PushdownStoreSymbolType, StateType > & pda );
 };
 
-template < class SymbolType, class StateType >
-automaton::DFA < SymbolType, unsigned > Rename::rename ( const automaton::DFA < SymbolType, StateType > & fsm ) {
-	unsigned counter = 0;
-	ext::map < StateType, unsigned > renamingData;
-
-	for ( const StateType & state : fsm.getStates ( ) )
-		renamingData.insert ( std::make_pair ( state, counter++ ) );
-
-	automaton::DFA < SymbolType, unsigned > result ( renamingData.at ( fsm.getInitialState ( ) ) );
-
-	result.setInputAlphabet ( fsm.getInputAlphabet ( ) );
-
-	for ( const StateType & state : fsm.getStates ( ) )
-		result.addState ( renamingData.at ( state ) );
-
-	for ( const StateType & state : fsm.getFinalStates ( ) )
-		result.addFinalState ( renamingData.at ( state ) );
-
-	for ( const auto & transition : fsm.getTransitions ( ) )
-		result.addTransition ( renamingData.at ( transition.first.first ), transition.first.second, renamingData.at ( transition.second ) );
-
-	return result;
-}
+template < class T >
+ext::require < isDFA < T > || isNFA < T >, Rename::RenamedAutomaton < T > > Rename::rename ( const T & fsm ) {
+	using StateType = automaton::StateTypeOfAutomaton < T >;
 
-template < class SymbolType, class StateType >
-automaton::NFA < SymbolType, unsigned > Rename::rename ( const automaton::NFA < SymbolType, StateType > & fsm ) {
 	unsigned counter = 0;
 	ext::map < StateType, unsigned > renamingData;
 
 	for ( const StateType & state : fsm.getStates ( ) )
 		renamingData.insert ( std::make_pair ( state, counter++ ) );
 
-	automaton::NFA < SymbolType, unsigned > result ( renamingData.at ( fsm.getInitialState ( ) ) );
+	Rename::RenamedAutomaton < T > result ( renamingData.at ( fsm.getInitialState ( ) ) );
 
 	result.setInputAlphabet ( fsm.getInputAlphabet ( ) );
 
diff --git a/alib2std/src/extensions/type_traits.hpp b/alib2std/src/extensions/type_traits.hpp
index a36d973597..63dc1e3dfc 100644
--- a/alib2std/src/extensions/type_traits.hpp
+++ b/alib2std/src/extensions/type_traits.hpp
@@ -138,6 +138,32 @@ namespace ext {
 	template < bool value, typename type = int >
 	using require = typename std::enable_if < value, type >::type;
 
+// ----------------------------------------------------------------------------------------------------
+
+	template < bool value>
+	using boolean = typename std::conditional < value, std::true_type, std::false_type >::type;
+
+	template < class ... Ts >
+	struct casional;
+
+	template < >
+	struct casional < > {
+		typedef void type;
+	};
+
+	template < class T >
+	struct casional < T > {
+		typedef T type;
+	};
+
+	template < class R, class ... Ts >
+	struct casional < std::true_type, R, Ts ... > : public casional < R > {
+	};
+
+	template < class R, class ... Ts >
+	struct casional < std::false_type, R, Ts ... > : public casional < Ts ... > {
+	};
+
 } /* namespace ext */
 
 #endif /* __TYPE_TRAITS_HPP_ */
-- 
GitLab