diff --git a/alib2algo/src/automaton/FSMSingleInitialState.cpp b/alib2algo/src/automaton/FSMSingleInitialState.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0e967cb5247efbc23ba17e1ac485b490327e6a09
--- /dev/null
+++ b/alib2algo/src/automaton/FSMSingleInitialState.cpp
@@ -0,0 +1,171 @@
+/*
+ * FSMSingleInitialState.cpp
+ *
+ *  Created on: 20. 9. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#include "FSMSingleInitialState.h"
+
+#include <algorithm>
+#include <set>
+
+#include <exception/AlibException.h>
+#include <automaton/FSM/NFA.h>
+#include <automaton/FSM/ExtendedNFA.h>
+#include <automaton/FSM/EpsilonNFA.h>
+#include <automaton/FSM/CompactNFA.h>
+
+namespace automaton {
+
+automaton::Automaton FSMSingleInitialState::convert(const Automaton& automaton) {
+	automaton::Automaton* out = NULL;
+	automaton.getData().Accept((void*) &out, FSMSingleInitialState::FSM_SINGLE_INITIAL_STATE);
+	automaton::Automaton res = std::move(*out);
+	delete out;
+	return res;
+}
+
+template<class T>
+T FSMSingleInitialState::convert(const T& automaton) {
+	if(automaton.getInitialStates().size() <= 1) {
+		return automaton;
+	}
+
+	// copy the automaton, remove all initial state flags
+	T res(automaton);
+	for(const auto& q : automaton.getInitialStates()) {
+		res.removeInitialState(q);
+	}
+
+	// step 3
+	automaton::State q0 = automaton::createUniqueState(automaton::State("q0"), res.getStates());
+	res.addState(q0);
+	res.addInitialState(q0);
+
+	// step 2
+	for(const auto& q : automaton.getInitialStates()) {
+		for(const auto& kv: automaton.getTransitionsFromState(q)) {
+			for(const auto& to : kv.second) {
+				res.addTransition(q0, kv.first.second, to);
+			}
+		}
+	}
+
+	// step 4, 5
+	std::set<automaton::State> intersection;
+	std::set_intersection(res.getFinalStates().begin(), res.getFinalStates().end(), automaton.getInitialStates().begin(), automaton.getInitialStates().end(), std::inserter(intersection, intersection.begin()));
+
+	res.setFinalStates(automaton.getFinalStates());
+	if(intersection.size() != 0) {
+		res.addFinalState(q0);
+	}
+
+	return res;
+}
+/*
+template automaton::NFA convert(const automaton::NFA& automaton);
+template automaton::ExtendedNFA convert(const automaton::ExtendedNFA& automaton);
+template automaton::CompactNFA convert(const automaton::CompactNFA& automaton);
+template automaton::EpsilonNFA convert(const automaton::EpsilonNFA& automaton);
+*/
+/*
+template<>
+automaton::EpsilonNFA convert(const automaton::EpsilonNFA& automaton) {
+	if(automaton.getInitialStates().size() <= 1) {
+		return automaton;
+	}
+
+	// copy the automaton, remove all initial state flags
+	automaton::T res(automaton);
+	for(const auto& q : automaton.getInitialStates()) {
+		res.removeInitialState(q);
+	}
+
+	// step 3
+	automaton::State q0 = automaton::createUniqueState(automaton::State("q0"), res.getStates());
+	res.addState(q0);
+	res.addInitialState(q0);
+
+	// step 2
+	for(const auto& q : automaton.getInitialStates()) {
+		for(const auto& kv: automaton.getTransitionsFromState(q)) {
+			for(const auto& to : kv.second) {
+				res.addTransition(q0, kv.first.second, to);
+			}
+		}
+	}
+
+	// step 4, 5
+	std::set<automaton::State> intersection;
+	std::set_intersection(res.getFinalStates().begin(), res.getFinalStates().end(), automaton.getInitialStates().begin(), automaton.getInitialStates().end(), std::inserter(intersection, intersection.begin()));
+
+	res.setFinalStates(automaton.getFinalStates());
+	if(intersection.size() != 0) {
+		res.addFinalState(q0);
+	}
+
+	return res;
+}
+*/
+
+void FSMSingleInitialState::Visit(void*, const UnknownAutomaton&) const {
+	throw exception::AlibException("Unsupported automaton type UnknownAutomaton");
+}
+
+void FSMSingleInitialState::Visit(void* data, const EpsilonNFA& automaton) const {
+	automaton::Automaton*& out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->convert(automaton));
+}
+
+void FSMSingleInitialState::Visit(void* data, const NFA& automaton) const {
+	automaton::Automaton*& out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->convert(automaton));
+}
+
+void FSMSingleInitialState::Visit(void*, const DFA&) const {
+	throw exception::AlibException("Unsupported automaton type DFA");
+}
+
+void FSMSingleInitialState::Visit(void* data, const ExtendedNFA& automaton) const {
+	automaton::Automaton*& out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->convert(automaton));
+}
+
+void FSMSingleInitialState::Visit(void* data, const CompactNFA& automaton) const {
+	automaton::Automaton*& out = *((automaton::Automaton**) data);
+	out = new automaton::Automaton(this->convert(automaton));
+}
+
+void FSMSingleInitialState::Visit(void*, const DPDA&) const {
+	throw exception::AlibException("Unsupported automaton type UnknownAutomaton");
+}
+
+void FSMSingleInitialState::Visit(void*, const SinglePopDPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
+}
+
+void FSMSingleInitialState::Visit(void*, const InputDrivenNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
+}
+
+void FSMSingleInitialState::Visit(void*, const VisiblyPushdownNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
+}
+
+void FSMSingleInitialState::Visit(void*, const NPDA&) const {
+	throw exception::AlibException("Unsupported automaton type NPDA");
+}
+
+void FSMSingleInitialState::Visit(void*, const SinglePopNPDA&) const {
+	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
+}
+
+void FSMSingleInitialState::Visit(void*, const OneTapeDTM&) const {
+	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
+}
+
+const FSMSingleInitialState FSMSingleInitialState::FSM_SINGLE_INITIAL_STATE;
+
+}
+
diff --git a/alib2algo/src/automaton/FSMSingleInitialState.h b/alib2algo/src/automaton/FSMSingleInitialState.h
new file mode 100644
index 0000000000000000000000000000000000000000..09b67a5f84ac3b0db60f74c86b84510a65d31f64
--- /dev/null
+++ b/alib2algo/src/automaton/FSMSingleInitialState.h
@@ -0,0 +1,55 @@
+/*
+ * FSMSingleInitialState.h
+ *
+ *  Created on: 20. 9. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef FSM_SINGLE_INITIAL_STATE_H
+#define FSM_SINGLE_INITIAL_STATE_H
+
+#include <automaton/Automaton.h>
+#include <automaton/common/State.h>
+
+namespace automaton {
+
+/**
+ * Makes finite automaton's transition function convert.
+ * Source: Melichar: Algorithm 2.22
+ */
+class FSMSingleInitialState : public VisitableAutomatonBase::const_visitor_type {
+public:
+	/**
+	 * Computes epsilon closure of a state in epsilon nonfree automaton
+	 */
+	static automaton::Automaton convert(const automaton::Automaton& automaton);
+
+	template<class T>
+	static T convert(const T& automaton);
+
+	//static automaton::NFA convert(const automaton::NFA& automaton);
+	//static automaton::EpsilonNFA convert(const automaton::EpsilonNFA& automaton);
+	//static automaton::ExtendedNFA convert(const automaton::ExtendedNFA& automaton);
+	//static automaton::CompactNFA convert(const automaton::CompactNFA& automaton);
+
+private:
+	void Visit(void*, const UnknownAutomaton& automaton) const;
+	void Visit(void*, const EpsilonNFA& automaton) const;
+	void Visit(void*, const NFA& automaton) const;
+	void Visit(void*, const DFA& automaton) const;
+	void Visit(void*, const ExtendedNFA& automaton) const;
+	void Visit(void*, const CompactNFA& automaton) const;
+	void Visit(void*, const DPDA& automaton) const;
+	void Visit(void*, const SinglePopDPDA& automaton) const;
+	void Visit(void*, const InputDrivenNPDA& automaton) const;
+	void Visit(void*, const VisiblyPushdownNPDA& automaton) const;
+	void Visit(void*, const NPDA& automaton) const;
+	void Visit(void*, const SinglePopNPDA& automaton) const;
+	void Visit(void*, const OneTapeDTM& automaton) const;
+
+	static const FSMSingleInitialState FSM_SINGLE_INITIAL_STATE;
+};
+
+}
+
+#endif /* FSM_SINGLE_INITIAL_STATE_H_ */
diff --git a/alib2algo/test-src/automaton/FSMSingleInitialStateTest.cpp b/alib2algo/test-src/automaton/FSMSingleInitialStateTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8388eb19a8959de7ff2a6fa2725f97ad14e29d58
--- /dev/null
+++ b/alib2algo/test-src/automaton/FSMSingleInitialStateTest.cpp
@@ -0,0 +1,58 @@
+#include "FSMSingleInitialStateTest.h"
+
+#include <alphabet/LabeledSymbol.h>
+#include <label/Label.h>
+#include <label/CharacterLabel.h>
+
+#include "automaton/FSMSingleInitialState.h"
+#include "determinize/nfa/NFADeterminizer.h"
+#include "normalize/dfa/NormalizeDFA.h"
+
+#define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y))
+
+CPPUNIT_TEST_SUITE_REGISTRATION( FSMSingleInitialStateTest );
+
+void FSMSingleInitialStateTest::setUp() {
+}
+
+void FSMSingleInitialStateTest::tearDown() {
+}
+
+void FSMSingleInitialStateTest::testSingleInitialState() {
+	automaton::State q("q");
+	automaton::State q0("q0");
+	automaton::State q1("q1");
+	automaton::State q2("q2");
+	automaton::State q3("q3");
+
+	alphabet::Symbol a(alphabet::LabeledSymbol(label::Label(label::CharacterLabel('a'))));
+	alphabet::Symbol b(alphabet::LabeledSymbol(label::Label(label::CharacterLabel('b'))));
+
+	automaton::NFA automaton1;
+	automaton1.setStates({q0, q1, q2, q3});
+	automaton1.setInitialStates({q0, q1, q2});
+	automaton1.setFinalStates({q3});
+	automaton1.setInputSymbols({a, b});
+	automaton1.addTransition(q0, a, q1);
+	automaton1.addTransition(q1, b, q2);
+	automaton1.addTransition(q2, a, q3);
+
+	automaton::NFA automaton2 = automaton::FSMSingleInitialState::convert(automaton1);
+	CPPUNIT_ASSERT(automaton2.getInitialStates().size() == 1);
+
+	automaton::NFA automaton3;
+	automaton3.setStates({q, q1, q2, q3});
+	automaton3.setInitialStates({q});
+	automaton3.setFinalStates({q3});
+	automaton3.setInputSymbols({a, b});
+	automaton3.addTransition(q, a, q3);
+	automaton3.addTransition(q, b, q2);
+	automaton3.addTransition(q, a, q1);
+	automaton3.addTransition(q1, b, q2);
+	automaton3.addTransition(q2, a, q3);
+
+	automaton::DFA dfa2 = determinize::NFADeterminizer::determinize(automaton2);
+	automaton::DFA dfa3 = determinize::NFADeterminizer::determinize(automaton3);
+
+	CPPUNIT_ASSERT(normalize::NormalizeDFA::normalize(dfa3) == normalize::NormalizeDFA::normalize(dfa3));
+}
diff --git a/alib2algo/test-src/automaton/FSMSingleInitialStateTest.h b/alib2algo/test-src/automaton/FSMSingleInitialStateTest.h
new file mode 100644
index 0000000000000000000000000000000000000000..fee9a58ef397311fbc268e6089a69f701592d295
--- /dev/null
+++ b/alib2algo/test-src/automaton/FSMSingleInitialStateTest.h
@@ -0,0 +1,19 @@
+#ifndef FSM_SINGLE_INITIAL_STATE_TEST_H_
+#define FSM_SINGLE_INITIAL_STATE_TEST_H_
+
+#include <cppunit/extensions/HelperMacros.h>
+
+class FSMSingleInitialStateTest : public CppUnit::TestFixture
+{
+  CPPUNIT_TEST_SUITE( FSMSingleInitialStateTest );
+  CPPUNIT_TEST( testSingleInitialState );
+  CPPUNIT_TEST_SUITE_END();
+
+public:
+  void setUp();
+  void tearDown();
+
+  void testSingleInitialState();
+};
+
+#endif /* FSM_SINGLE_INITIAL_STATE_TEST_H_ */