diff --git a/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.cpp b/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e5db1d4b20116bd3196797f9c544bd692109d833
--- /dev/null
+++ b/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.cpp
@@ -0,0 +1,178 @@
+/*
+ * AutomataUnionCartesianProduct.cpp
+ *
+ *  Created on: 20. 11. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#include "AutomataUnionCartesianProduct.h"
+#include <exception/AlibException.h>
+#include "common/PairLabel.h"
+
+#define AUTOMATON_FIRST  1
+#define AUTOMATON_SECOND 2
+
+namespace automaton
+{
+
+namespace transform
+{
+
+automaton::Automaton AutomataUnionCartesianProduct::unification(const automaton::Automaton& first, const automaton::Automaton& second)
+{
+	AutomatonBase* out;
+	Accept((void*) &out, first.getData(), second.getData(), AutomataUnionCartesianProduct::AUTOMATA_UNION_CARTESIAN_PRODUCT);
+	automaton::Automaton res(*out);
+	delete out;
+	return res;
+}
+
+automaton::DFA AutomataUnionCartesianProduct::unification(const automaton::DFA& first, const automaton::DFA& second)
+{
+	automaton::State q0(pairLabel(first.getInitialState(), second.getInitialState()));
+	automaton::DFA res(q0);
+
+	for(const auto& a : first.getInputAlphabet())
+		res.addInputSymbol(a);
+	for(const auto& a : second.getInputAlphabet())
+		res.addInputSymbol(a);
+
+	for(const auto& p : first.getStates())
+		for(const auto& q : second.getStates())
+			res.addState(automaton::State(pairLabel(p, q)));
+
+	for(const auto& p : first.getFinalStates())
+		for(const auto& q : second.getStates())
+			res.addFinalState(automaton::State(pairLabel(p, q)));
+
+	for(const auto& p : first.getStates())
+		for(const auto& q : second.getFinalStates())
+			res.addFinalState(automaton::State(pairLabel(p, q)));
+
+	for(const auto& tp : first.getTransitions())
+		for(const auto& tq : second.getTransitions())
+			if(tp.first.second == tq.first.second)
+				res.addTransition(automaton::State(pairLabel(tp.first.first, tq.first.first)), tp.first.second, automaton::State(pairLabel(tp.second, tq.second)));
+
+	return res;
+}
+
+automaton::NFA AutomataUnionCartesianProduct::unification(const automaton::NFA& first, const automaton::NFA& second)
+{
+	automaton::State q0(pairLabel(first.getInitialState(), second.getInitialState()));
+	automaton::NFA res(q0);
+
+	for(const auto& a : first.getInputAlphabet())
+		res.addInputSymbol(a);
+	for(const auto& a : second.getInputAlphabet())
+		res.addInputSymbol(a);
+
+	for(const auto& p : first.getStates())
+		for(const auto& q : second.getStates())
+			res.addState(automaton::State(pairLabel(p, q)));
+
+	for(const auto& p : first.getFinalStates())
+		for(const auto& q : second.getStates())
+			res.addFinalState(automaton::State(pairLabel(p, q)));
+
+	for(const auto& p : first.getStates())
+		for(const auto& q : second.getFinalStates())
+			res.addFinalState(automaton::State(pairLabel(p, q)));
+
+	for(const auto& tp : first.getTransitions())
+		for(const auto& tq : second.getTransitions())
+			if(tp.first.second == tq.first.second)
+				for(const auto& p : tp.second)
+					for(const auto& q : tq.second)
+						res.addTransition(automaton::State(pairLabel(tp.first.first, tq.first.first)), tp.first.second, automaton::State(pairLabel(p, q)));
+
+	return res;
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::EpsilonNFA&, const automaton::EpsilonNFA&) const
+{
+	throw exception::AlibException("Unsupported automaton type EpsilonNFA");
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::CompactNFA&, const automaton::CompactNFA&) const
+{
+	throw exception::AlibException("Unsupported automaton type CompactNFA");
+}
+
+void AutomataUnionCartesianProduct::Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const
+{
+	AutomatonBase* &ret = *(AutomatonBase**) data;
+	ret = std::move(AutomataUnionCartesianProduct::unification(first, second)).plunder();
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::ExtendedNFA&, const automaton::ExtendedNFA&) const
+{
+	throw exception::AlibException("Unsupported automaton type ExtendedNFA");
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::MultiInitialStateNFA&, const automaton::MultiInitialStateNFA&) const
+{
+	throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA");
+}
+
+void AutomataUnionCartesianProduct::Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const
+{
+	AutomatonBase* &ret = *(AutomatonBase**) data;
+	ret = std::move(AutomataUnionCartesianProduct::unification(first, second)).plunder();
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::DPDA&, const automaton::DPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type DPDA");
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::NPDA&, const automaton::NPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type NPDA");
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::InputDrivenNPDA&, const automaton::InputDrivenNPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::RealTimeHeightDeterministicDPDA&, const automaton::RealTimeHeightDeterministicDPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA");
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::RealTimeHeightDeterministicNPDA&, const automaton::RealTimeHeightDeterministicNPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA");
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::SinglePopNPDA&, const automaton::SinglePopNPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::SinglePopDPDA&, const automaton::SinglePopDPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::VisiblyPushdownDPDA&, const automaton::VisiblyPushdownDPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA");
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::VisiblyPushdownNPDA&, const automaton::VisiblyPushdownNPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
+}
+
+void AutomataUnionCartesianProduct::Visit(void*, const automaton::OneTapeDTM&, const automaton::OneTapeDTM&) const
+{
+	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
+}
+
+const AutomataUnionCartesianProduct AutomataUnionCartesianProduct::AUTOMATA_UNION_CARTESIAN_PRODUCT;
+
+} /* namespace transform */
+
+} /* namespace automaton */
diff --git a/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.h b/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.h
new file mode 100644
index 0000000000000000000000000000000000000000..305efabc5f7f082bcf9b98a4d322579f33181af3
--- /dev/null
+++ b/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.h
@@ -0,0 +1,59 @@
+/*
+ * AutomataUnionCartesianProduct.h
+ *
+ *  Created on: 20. 11. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef AUTOMATA_UNION_CARTESIAN_H_
+#define AUTOMATA_UNION_CARTESIAN_H_
+
+#include <automaton/Automaton.h>
+#include <automaton/FSM/EpsilonNFA.h>
+
+namespace automaton
+{
+
+namespace transform
+{
+
+/**
+ * Union two automata.
+ *  - For finite automata A1, A2, we create automaton L accepting L(A1) \cup L(A2) (Melichar, 2.71)
+ */
+class AutomataUnionCartesianProduct : public automaton::VisitableAutomatonBase::const_promoting_visitor_type
+{
+public:
+	static automaton::Automaton unification(const automaton::Automaton& first, const automaton::Automaton& second);
+
+	static automaton::NFA unification(const automaton::NFA& first, const automaton::NFA& second);
+	static automaton::DFA unification(const automaton::DFA& first, const automaton::DFA& second);
+
+private:
+	void Visit(void* data, const automaton::CompactNFA& first, const automaton::CompactNFA& second) const;
+	void Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const;
+	void Visit(void* data, const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) const;
+	void Visit(void* data, const automaton::ExtendedNFA& first, const automaton::ExtendedNFA& second) const;
+	void Visit(void* data, const automaton::MultiInitialStateNFA& first, const automaton::MultiInitialStateNFA& second) const;
+	void Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const;
+
+	void Visit(void* data, const automaton::DPDA& first, const automaton::DPDA& second) const;
+	void Visit(void* data, const automaton::NPDA& first, const automaton::NPDA& second) const;
+	void Visit(void* data, const automaton::InputDrivenNPDA& first, const automaton::InputDrivenNPDA& second) const;
+	void Visit(void* data, const automaton::RealTimeHeightDeterministicDPDA& first, const automaton::RealTimeHeightDeterministicDPDA& second) const;
+	void Visit(void* data, const automaton::RealTimeHeightDeterministicNPDA& first, const automaton::RealTimeHeightDeterministicNPDA& second) const;
+	void Visit(void* data, const automaton::SinglePopNPDA& first, const automaton::SinglePopNPDA& second) const;
+	void Visit(void* data, const automaton::SinglePopDPDA& first, const automaton::SinglePopDPDA& second) const;
+	void Visit(void* data, const automaton::VisiblyPushdownDPDA& first, const automaton::VisiblyPushdownDPDA& second) const;
+	void Visit(void* data, const automaton::VisiblyPushdownNPDA& first, const automaton::VisiblyPushdownNPDA& second) const;
+
+	void Visit(void* data, const automaton::OneTapeDTM& first, const automaton::OneTapeDTM& second) const;
+
+	static const AutomataUnionCartesianProduct AUTOMATA_UNION_CARTESIAN_PRODUCT;
+};
+
+} /* namespace transform */
+
+} /* namespace automaton */
+
+#endif /* AUTOMATA_UNION_CARTESIAN_H_ */
diff --git a/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.cpp b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..848135ec651125cbf79921a4f98ee7ef0069b726
--- /dev/null
+++ b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.cpp
@@ -0,0 +1,229 @@
+/*
+ * AutomataUnionEpsilonTransition.cpp
+ *
+ *  Created on: 20. 11. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#include "AutomataUnionEpsilonTransition.h"
+#include <exception/AlibException.h>
+#include "common/PairLabel.h"
+
+#define AUTOMATON_FIRST  1
+#define AUTOMATON_SECOND 2
+
+namespace automaton
+{
+
+namespace transform
+{
+
+automaton::Automaton AutomataUnionEpsilonTransition::unification(const automaton::Automaton& first, const automaton::Automaton& second)
+{
+	AutomatonBase* out;
+	Accept((void*) &out, first.getData(), second.getData(), AutomataUnionEpsilonTransition::AUTOMATA_UNION_EPSILON_TRANSITION);
+	automaton::Automaton res(*out);
+	delete out;
+	return res;
+}
+
+automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second)
+{
+	std::set<automaton::State> states;
+	for(const auto& q : first.getStates())
+		states.insert(pairLabel(label::labelFrom(AUTOMATON_FIRST), q));
+	for(const auto& q : second.getStates())
+		states.insert(pairLabel(label::labelFrom(AUTOMATON_SECOND), q));
+
+	automaton::State q0 = automaton::createUniqueState(automaton::State("q0"), states);
+	automaton::EpsilonNFA res(q0);
+
+	for(const auto& a : first.getInputAlphabet())
+		res.addInputSymbol(a);
+	for(const auto& a : second.getInputAlphabet())
+		res.addInputSymbol(a);
+
+	for(const auto& q : states)
+		res.addState(q);
+
+	for(const auto& q : first.getFinalStates())
+		res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_FIRST), q));
+	for(const auto& q : second.getFinalStates())
+		res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_SECOND), q));
+
+	res.addTransition(q0, pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState()));
+	res.addTransition(q0, pairLabel(label::labelFrom(AUTOMATON_SECOND), second.getInitialState()));
+
+	for(const auto& t : first.getTransitions())
+		for(const auto& q : t.second)
+			res.addTransition(pairLabel(label::labelFrom(AUTOMATON_FIRST), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_FIRST), q));
+
+	for(const auto& t : second.getTransitions())
+		for(const auto& q : t.second)
+			res.addTransition(pairLabel(label::labelFrom(AUTOMATON_SECOND), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_SECOND), q));
+
+	return res;
+}
+
+automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automaton::NFA& first, const automaton::NFA& second)
+{
+	std::set<automaton::State> states;
+	for(const auto& q : first.getStates())
+		states.insert(pairLabel(label::labelFrom(AUTOMATON_FIRST), q));
+	for(const auto& q : second.getStates())
+		states.insert(pairLabel(label::labelFrom(AUTOMATON_SECOND), q));
+
+	automaton::State q0 = automaton::createUniqueState(automaton::State("q0"), states);
+	automaton::EpsilonNFA res(q0);
+
+	for(const auto& a : first.getInputAlphabet())
+		res.addInputSymbol(a);
+	for(const auto& a : second.getInputAlphabet())
+		res.addInputSymbol(a);
+
+	for(const auto& q : states)
+		res.addState(q);
+
+	for(const auto& q : first.getFinalStates())
+		res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_FIRST), q));
+	for(const auto& q : second.getFinalStates())
+		res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_SECOND), q));
+
+	res.addTransition(q0, pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState()));
+	res.addTransition(q0, pairLabel(label::labelFrom(AUTOMATON_SECOND), second.getInitialState()));
+
+	for(const auto& t : first.getTransitions())
+		for(const auto& q : t.second)
+			res.addTransition(pairLabel(label::labelFrom(AUTOMATON_FIRST), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_FIRST), q));
+
+	for(const auto& t : second.getTransitions())
+		for(const auto& q : t.second)
+			res.addTransition(pairLabel(label::labelFrom(AUTOMATON_SECOND), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_SECOND), q));
+
+	return res;
+}
+
+automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automaton::DFA& first, const automaton::DFA& second)
+{
+	std::set<automaton::State> states;
+	for(const auto& q : first.getStates())
+		states.insert(pairLabel(label::labelFrom(AUTOMATON_FIRST), q));
+	for(const auto& q : second.getStates())
+		states.insert(pairLabel(label::labelFrom(AUTOMATON_SECOND), q));
+
+	automaton::State q0 = automaton::createUniqueState(automaton::State("q0"), states);
+	automaton::EpsilonNFA res(q0);
+
+	for(const auto& a : first.getInputAlphabet())
+		res.addInputSymbol(a);
+	for(const auto& a : second.getInputAlphabet())
+		res.addInputSymbol(a);
+
+	for(const auto& q : states)
+		res.addState(q);
+
+	for(const auto& q : first.getFinalStates())
+		res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_FIRST), q));
+	for(const auto& q : second.getFinalStates())
+		res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_SECOND), q));
+
+	res.addTransition(q0, pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState()));
+	res.addTransition(q0, pairLabel(label::labelFrom(AUTOMATON_SECOND), second.getInitialState()));
+
+	for(const auto& t : first.getTransitions())
+		res.addTransition(pairLabel(label::labelFrom(AUTOMATON_FIRST), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_FIRST), t.second));
+
+	for(const auto& t : second.getTransitions())
+		res.addTransition(pairLabel(label::labelFrom(AUTOMATON_SECOND), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_SECOND), t.second));
+
+	return res;
+}
+
+void AutomataUnionEpsilonTransition::Visit(void* data, const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) const
+{
+	AutomatonBase* &ret = *(AutomatonBase**) data;
+	ret = std::move(AutomataUnionEpsilonTransition::unification(first, second)).plunder();
+}
+
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::CompactNFA&, const automaton::CompactNFA&) const
+{
+	throw exception::AlibException("Unsupported automaton type CompactNFA");
+}
+
+void AutomataUnionEpsilonTransition::Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const
+{
+	AutomatonBase* &ret = *(AutomatonBase**) data;
+	ret = std::move(AutomataUnionEpsilonTransition::unification(first, second)).plunder();
+}
+
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::ExtendedNFA&, const automaton::ExtendedNFA&) const
+{
+	throw exception::AlibException("Unsupported automaton type ExtendedNFA");
+}
+
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::MultiInitialStateNFA&, const automaton::MultiInitialStateNFA&) const
+{
+	throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA");
+}
+
+void AutomataUnionEpsilonTransition::Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const
+{
+	AutomatonBase* &ret = *(AutomatonBase**) data;
+	ret = std::move(AutomataUnionEpsilonTransition::unification(first, second)).plunder();
+}
+
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::DPDA&, const automaton::DPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type DPDA");
+}
+
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::NPDA&, const automaton::NPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type NPDA");
+}
+
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::InputDrivenNPDA&, const automaton::InputDrivenNPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
+}
+
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::RealTimeHeightDeterministicDPDA&, const automaton::RealTimeHeightDeterministicDPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA");
+}
+
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::RealTimeHeightDeterministicNPDA&, const automaton::RealTimeHeightDeterministicNPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA");
+}
+
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::SinglePopNPDA&, const automaton::SinglePopNPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
+}
+
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::SinglePopDPDA&, const automaton::SinglePopDPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
+}
+
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::VisiblyPushdownDPDA&, const automaton::VisiblyPushdownDPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA");
+}
+
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::VisiblyPushdownNPDA&, const automaton::VisiblyPushdownNPDA&) const
+{
+	throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
+}
+
+void AutomataUnionEpsilonTransition::Visit(void*, const automaton::OneTapeDTM&, const automaton::OneTapeDTM&) const
+{
+	throw exception::AlibException("Unsupported automaton type OneTapeDTM");
+}
+
+const AutomataUnionEpsilonTransition AutomataUnionEpsilonTransition::AUTOMATA_UNION_EPSILON_TRANSITION;
+
+} /* namespace transform */
+
+} /* namespace automaton */
diff --git a/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h
new file mode 100644
index 0000000000000000000000000000000000000000..855fc5b94d9b4ffa067785c0b14a1f87a9a5a2a7
--- /dev/null
+++ b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h
@@ -0,0 +1,60 @@
+/*
+ * AutomataUnionEpsilonTransition.h
+ *
+ *  Created on: 20. 11. 2014
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef AUTOMATA_UNION_EPSILON_H_
+#define AUTOMATA_UNION_EPSILON_H_
+
+#include <automaton/Automaton.h>
+#include <automaton/FSM/EpsilonNFA.h>
+
+namespace automaton
+{
+
+namespace transform
+{
+
+/**
+ * Union two automata.
+ *  - For finite automata A1, A2, we create automaton L accepting L(A1) \cup L(A2)
+ */
+class AutomataUnionEpsilonTransition : public automaton::VisitableAutomatonBase::const_promoting_visitor_type
+{
+public:
+	static automaton::Automaton unification(const automaton::Automaton& first, const automaton::Automaton& second);
+
+	static automaton::EpsilonNFA unification(const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second);
+	static automaton::EpsilonNFA unification(const automaton::NFA& first, const automaton::NFA& second);
+	static automaton::EpsilonNFA unification(const automaton::DFA& first, const automaton::DFA& second);
+
+private:
+	void Visit(void* data, const automaton::CompactNFA& first, const automaton::CompactNFA& second) const;
+	void Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const;
+	void Visit(void* data, const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) const;
+	void Visit(void* data, const automaton::ExtendedNFA& first, const automaton::ExtendedNFA& second) const;
+	void Visit(void* data, const automaton::MultiInitialStateNFA& first, const automaton::MultiInitialStateNFA& second) const;
+	void Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const;
+
+	void Visit(void* data, const automaton::DPDA& first, const automaton::DPDA& second) const;
+	void Visit(void* data, const automaton::NPDA& first, const automaton::NPDA& second) const;
+	void Visit(void* data, const automaton::InputDrivenNPDA& first, const automaton::InputDrivenNPDA& second) const;
+	void Visit(void* data, const automaton::RealTimeHeightDeterministicDPDA& first, const automaton::RealTimeHeightDeterministicDPDA& second) const;
+	void Visit(void* data, const automaton::RealTimeHeightDeterministicNPDA& first, const automaton::RealTimeHeightDeterministicNPDA& second) const;
+	void Visit(void* data, const automaton::SinglePopNPDA& first, const automaton::SinglePopNPDA& second) const;
+	void Visit(void* data, const automaton::SinglePopDPDA& first, const automaton::SinglePopDPDA& second) const;
+	void Visit(void* data, const automaton::VisiblyPushdownDPDA& first, const automaton::VisiblyPushdownDPDA& second) const;
+	void Visit(void* data, const automaton::VisiblyPushdownNPDA& first, const automaton::VisiblyPushdownNPDA& second) const;
+
+	void Visit(void* data, const automaton::OneTapeDTM& first, const automaton::OneTapeDTM& second) const;
+
+	static const AutomataUnionEpsilonTransition AUTOMATA_UNION_EPSILON_TRANSITION;
+};
+
+} /* namespace transform */
+
+} /* namespace automaton */
+
+#endif /* AUTOMATA_UNION_EPSILON_H_ */