From 19387c37450e9fc42b8cc86e9e737b0de14a5bd2 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Tue, 17 Sep 2019 08:47:33 +0200
Subject: [PATCH] remove duplicate code in single initial state algo

---
 .../automaton/simplify/SingleInitialState.h   | 138 +++++-------------
 1 file changed, 40 insertions(+), 98 deletions(-)

diff --git a/alib2algo/src/automaton/simplify/SingleInitialState.h b/alib2algo/src/automaton/simplify/SingleInitialState.h
index 8c2f55b8ff..dc1516a74d 100644
--- a/alib2algo/src/automaton/simplify/SingleInitialState.h
+++ b/alib2algo/src/automaton/simplify/SingleInitialState.h
@@ -49,133 +49,75 @@ namespace simplify {
  * @sa automaton::simplify::SingleInitialStateEpsilonTransition
  */
 class SingleInitialState {
+	template < class T >
+	struct NFATra {
+		using type = automaton::NFA < typename T::SymbolType, typename T::StateType >;
+	};
+
+	template < class T >
+	struct EpsilonNFATra {
+		using type = automaton::EpsilonNFA < typename T::SymbolType, typename T::StateType >;
+	};
+
+	template < class T >
+	using ConvertedAutomaton = typename ext::casional <
+			ext::boolean < isMultiInitialStateNFA < T > >, NFATra < T >,
+			ext::boolean < isMultiInitialStateEpsilonNFA < T > >, EpsilonNFATra < T >
+		>::type::type;
+
 public:
 	/**
 	 * Converts multi-initial state automaton to a single-initial state automaton.
-	 * @tparam SymbolType Type for input symbols.
-	 * @tparam StateType Type for states.
+	 *
+	 * @tparam T type of the converted automaton.
+	 *
 	 * @param automaton automaton to convert
+	 *
 	 * @return an automaton equivalent to @p with only one initial state
 	 */
-	template < class SymbolType, class StateType >
-	static automaton::NFA < SymbolType, StateType > convert(const automaton::MultiInitialStateNFA < SymbolType, StateType > & automaton);
-
-	/**
-	 * @overload
-	 */
-	template < class SymbolType, class StateType >
-	static automaton::EpsilonNFA < SymbolType, StateType > convert(const automaton::MultiInitialStateEpsilonNFA < SymbolType, StateType > & automaton);
-
-	/**
-	 * @overload
-	 */
-	template < class SymbolType, class StateType >
-	static automaton::DFA < SymbolType, StateType > convert(const automaton::DFA < SymbolType, StateType > & automaton);
-
-	/**
-	 * @overload
-	 */
-	template < class SymbolType, class StateType >
-	static automaton::NFA < SymbolType, StateType > convert(const automaton::NFA < SymbolType, StateType > & automaton);
-
-	/**
-	 * @overload
-	 */
-	template < class SymbolType, class StateType >
-	static automaton::EpsilonNFA < SymbolType, StateType > convert(const automaton::EpsilonNFA < SymbolType, StateType > & automaton);
+	template < class T >
+	static ext::require < isMultiInitialStateNFA < T > || isMultiInitialStateEpsilonNFA < T >, SingleInitialState::ConvertedAutomaton < T > > convert ( const T & fsm );
 
 	/**
 	 * @overload
 	 */
-	template < class SymbolType, class StateType >
-	static automaton::ExtendedNFA < SymbolType, StateType > convert(const automaton::ExtendedNFA < SymbolType, StateType > & automaton);
-
-	/**
-	 * @overload
-	 */
-	template < class SymbolType, class StateType >
-	static automaton::CompactNFA < SymbolType, StateType > convert(const automaton::CompactNFA < SymbolType, StateType > & automaton);
+	template < class T >
+	static ext::require < isDFA < T > || isNFA < T > || isEpsilonNFA < T > || isExtendedNFA < T > || isCompactNFA < T >, T > convert ( const T & fsm );
 };
 
-template < class SymbolType, class StateType >
-automaton::NFA < SymbolType, StateType > SingleInitialState::convert(const automaton::MultiInitialStateNFA < SymbolType, StateType > & automaton) {
-	// step 1, 3
-	StateType q0 = common::createUnique ( label::InitialStateLabel::instance < StateType > ( ), automaton.getStates ( ) );
-
-	automaton::NFA < SymbolType, StateType > res ( q0 );
-	res.setInputAlphabet ( automaton.getInputAlphabet ( ) );
-
-	for( const StateType & q : automaton.getStates ( ) )
-		res.addState( q );
-
-	// step 2
-	for ( const auto & q : automaton.getInitialStates ( ) )
-		for(const auto & kv : automaton.getTransitionsFromState ( q ) )
-			res.addTransition ( q0, kv.first.second, kv.second );
-
-	for ( const auto & t : automaton.getTransitions ( ) )
-		res.addTransition ( t.first.first, t.first.second, t.second );
-
-	res.setFinalStates ( automaton.getFinalStates ( ) );
-
-	// step 4, 5
-	if ( ! ext::excludes ( automaton.getFinalStates ( ).begin ( ), automaton.getFinalStates ( ).end ( ), automaton.getInitialStates ( ).begin ( ), automaton.getInitialStates ( ).end ( ) ) )
-		res.addFinalState ( q0 );
-
-	return res;
-}
+template < class T >
+ext::require < isMultiInitialStateNFA < T > || isMultiInitialStateEpsilonNFA < T >, SingleInitialState::ConvertedAutomaton < T > > SingleInitialState::convert ( const T & fsm ) {
+	using StateType = typename T::StateType;
 
-template < class SymbolType, class StateType >
-automaton::EpsilonNFA < SymbolType, StateType > SingleInitialState::convert(const automaton::MultiInitialStateEpsilonNFA < SymbolType, StateType > & automaton) {
 	// step 1, 3
-	StateType q0 = common::createUnique ( label::InitialStateLabel::instance < StateType > ( ), automaton.getStates ( ) );
+	StateType q0 = common::createUnique ( label::InitialStateLabel::instance < StateType > ( ), fsm.getStates ( ) );
 
-	automaton::EpsilonNFA < SymbolType, StateType > res ( q0 );
-	res.setInputAlphabet ( automaton.getInputAlphabet ( ) );
+	SingleInitialState::ConvertedAutomaton < T > res ( q0 );
+	res.setInputAlphabet ( fsm.getInputAlphabet ( ) );
 
-	for( const StateType & q : automaton.getStates ( ) )
-		res.addState( q );
+	for( const StateType & q : fsm.getStates ( ) )
+		res.addState ( q );
 
 	// step 2
-	for ( const auto & q : automaton.getInitialStates ( ) )
-		for(const auto & kv : automaton.getTransitionsFromState ( q ) )
+	for ( const auto & q : fsm.getInitialStates ( ) )
+		for(const auto & kv : fsm.getTransitionsFromState ( q ) )
 			res.addTransition ( q0, kv.first.second, kv.second );
 
-	for ( const auto & t : automaton.getTransitions ( ) )
+	for ( const auto & t : fsm.getTransitions ( ) )
 		res.addTransition ( t.first.first, t.first.second, t.second );
 
-	res.setFinalStates ( automaton.getFinalStates ( ) );
+	res.setFinalStates ( fsm.getFinalStates ( ) );
 
 	// step 4, 5
-	if ( ! ext::excludes ( automaton.getFinalStates ( ).begin ( ), automaton.getFinalStates ( ).end ( ), automaton.getInitialStates ( ).begin ( ), automaton.getInitialStates ( ).end ( ) ) )
+	if ( ! ext::excludes ( fsm.getFinalStates ( ).begin ( ), fsm.getFinalStates ( ).end ( ), fsm.getInitialStates ( ).begin ( ), fsm.getInitialStates ( ).end ( ) ) )
 		res.addFinalState ( q0 );
 
 	return res;
 }
 
-template < class SymbolType, class StateType >
-automaton::DFA < SymbolType, StateType > SingleInitialState::convert(const automaton::DFA < SymbolType, StateType > & automaton) {
-	return automaton;
-}
-
-template < class SymbolType, class StateType >
-automaton::EpsilonNFA < SymbolType, StateType > SingleInitialState::convert(const automaton::EpsilonNFA < SymbolType, StateType > & automaton) {
-	return automaton;
-}
-
-template < class SymbolType, class StateType >
-automaton::NFA < SymbolType, StateType > SingleInitialState::convert(const automaton::NFA < SymbolType, StateType > & automaton) {
-	return automaton;
-}
-
-template < class SymbolType, class StateType >
-automaton::CompactNFA < SymbolType, StateType > SingleInitialState::convert(const automaton::CompactNFA < SymbolType, StateType > & automaton) {
-	return automaton;
-}
-
-template < class SymbolType, class StateType >
-automaton::ExtendedNFA < SymbolType, StateType > SingleInitialState::convert(const automaton::ExtendedNFA < SymbolType, StateType > & automaton) {
-	return automaton;
+template < class T >
+ext::require < isDFA < T > || isNFA < T > || isEpsilonNFA < T > || isExtendedNFA < T > || isCompactNFA < T >, T > SingleInitialState::convert ( const T & fsm ) {
+	return fsm;
 }
 
 } /* namespace simplify */
-- 
GitLab