From 5536dd20d0c981b96fe62fe4133a68430847803e Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Tue, 25 Oct 2016 15:58:58 +0200
Subject: [PATCH] fix iteration of automata

---
 .../transform/AutomatonIteration.cpp          | 36 ++++++++++++++++---
 .../automaton/transform/AutomatonIteration.h  |  4 +--
 .../AutomatonIterationEpsilonTransition.cpp   |  7 +++-
 .../transform/AutomatonIterationTest.cpp      | 19 ++++++----
 4 files changed, 52 insertions(+), 14 deletions(-)

diff --git a/alib2algo/src/automaton/transform/AutomatonIteration.cpp b/alib2algo/src/automaton/transform/AutomatonIteration.cpp
index 95bd5ee7bb..704657ba66 100644
--- a/alib2algo/src/automaton/transform/AutomatonIteration.cpp
+++ b/alib2algo/src/automaton/transform/AutomatonIteration.cpp
@@ -15,20 +15,46 @@ automaton::Automaton AutomatonIteration::iteration(const automaton::Automaton& a
 	return dispatch(automaton.getData());
 }
 
-template<class T>
-automaton::NFA < > AutomatonIteration::iteration(const T& automaton) {
+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());
 
-	res.addFinalState(automaton.getInitialState());
+	label::Label newInitialState = label::createUniqueLabel(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 = label::createUniqueLabel(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 AutomatonIterationDFA = AutomatonIteration::RegistratorWrapper<automaton::NFA < > , automaton::DFA<>>(AutomatonIteration::iteration);
-auto AutomatonIterationNFA = AutomatonIteration::RegistratorWrapper<automaton::NFA < > , automaton::NFA < > >(AutomatonIteration::iteration);
+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 5ae24fb04d..e05ef2e1f6 100644
--- a/alib2algo/src/automaton/transform/AutomatonIteration.h
+++ b/alib2algo/src/automaton/transform/AutomatonIteration.h
@@ -24,8 +24,8 @@ class AutomatonIteration : public std::SingleDispatch<AutomatonIteration, automa
 public:
 	static automaton::Automaton iteration(const automaton::Automaton& automaton);
 
-	template<class T>
-	static automaton::NFA < > iteration(const T& automaton);
+	static automaton::NFA < > iteration(const automaton::DFA < > & automaton);
+	static automaton::NFA < > iteration(const automaton::NFA < > & automaton);
 };
 
 } /* namespace transform */
diff --git a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
index d222a41262..d73327dcce 100644
--- a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
+++ b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp
@@ -22,7 +22,12 @@ automaton::EpsilonNFA < > AutomatonIterationEpsilonTransition::iteration(const T
 	for(const auto&q : automaton.getFinalStates())
 		res.addTransition(q, automaton.getInitialState());
 
-	res.addFinalState(automaton.getInitialState());
+	label::Label newInitialState = label::createUniqueLabel(automaton.getInitialState(), automaton.getStates());
+	res.addState(newInitialState);
+	res.setInitialState(newInitialState);
+	res.addFinalState(newInitialState);
+
+	res.addTransition(newInitialState, automaton.getInitialState());
 	return res;
 }
 
diff --git a/alib2algo/test-src/automaton/transform/AutomatonIterationTest.cpp b/alib2algo/test-src/automaton/transform/AutomatonIterationTest.cpp
index d059e5cfa0..20bfd484f2 100644
--- a/alib2algo/test-src/automaton/transform/AutomatonIterationTest.cpp
+++ b/alib2algo/test-src/automaton/transform/AutomatonIterationTest.cpp
@@ -25,27 +25,34 @@ void AutomatonIterationTest::tearDown() {
 void AutomatonIterationTest::testAutomatonIteration() {
 
 	// Melichar 2.83
+	label::Label q0 = label::labelFrom(0);
 	label::Label q1 = label::labelFrom(1);
 	label::Label q2 = label::labelFrom(2);
 	label::Label q3 = label::labelFrom(3);
-	alphabet::Symbol a(alphabet::symbolFrom('a')), b(alphabet::symbolFrom('b'));
+	alphabet::Symbol a = alphabet::symbolFrom('a');
+	alphabet::Symbol b = alphabet::symbolFrom('b');
 
-	automaton::DFA<> m1(q1);
+	automaton::DFA < > m1(q1);
 	m1.setStates({q1, q2, q3});
 	m1.addFinalState(q3);
 	m1.setInputAlphabet({a, b});
 	m1.addTransition(q1, a, q2);
 	m1.addTransition(q2, b, q2);
 	m1.addTransition(q2, a, q3);
+	m1.addTransition(q3, a, q1);
 
-	automaton::NFA < >  res(q1);
-	res.setStates({q1, q2, q3});
+	automaton::EpsilonNFA < > res(q0);
+	res.setStates({q0, q1, q2, q3});
 	res.setInputAlphabet({a, b});
-	res.setFinalStates({q1, q3});
+	res.setFinalStates({q0, q3});
+
 	res.addTransition(q1, a, q2);
 	res.addTransition(q2, b, q2);
 	res.addTransition(q2, a, q3);
-	res.addTransition(q2, a, q1);
+	res.addTransition(q3, a, q1);
+
+	res.addTransition(q0, q1);
+	res.addTransition(q3, q1);
 
 	automaton::Automaton i2 = automaton::transform::AutomatonIterationEpsilonTransition::iteration(automaton::Automaton(m1));
 	automaton::Automaton i1 = automaton::transform::AutomatonIteration::iteration(automaton::Automaton(m1));
-- 
GitLab