diff --git a/alib2data/src/automaton/FSM/DFA.cpp b/alib2data/src/automaton/FSM/DFA.cpp
index ec5169eedaccea3d45258bdc3f1652448d8124e9..41a93b6dcbfbd6548c9dda5651fa037f76a22bd7 100644
--- a/alib2data/src/automaton/FSM/DFA.cpp
+++ b/alib2data/src/automaton/FSM/DFA.cpp
@@ -133,16 +133,25 @@ bool DFA::isTotal() const {
 }
 
 int DFA::compare(const DFA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	std::compare<decltype(states)> comp;
+	int res = comp(states, other.states);
+	if(res == 0) {
+		std::compare<decltype(inputAlphabet)> comp;
+		res = comp(inputAlphabet, other.inputAlphabet);
 	}
+	if(res == 0) {
+		std::compare<decltype(initialState)> comp;
+		res = comp(initialState, other.initialState);
+	}
+	if(res == 0) {
+		std::compare<decltype(finalStates)> comp;
+		res = comp(finalStates, other.finalStates);
+	}
+	if(res == 0) {
+		std::compare<decltype(transitions)> comp;
+		res = comp(transitions, other.transitions);
+	}
+	return res;
 }
 
 void DFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/EpsilonNFA.cpp b/alib2data/src/automaton/FSM/EpsilonNFA.cpp
index c053207f2272d7a16ed01759d7f3347de36c6fea..1dc580bef8d5e940ced2269775aa8a49d69a4e5b 100644
--- a/alib2data/src/automaton/FSM/EpsilonNFA.cpp
+++ b/alib2data/src/automaton/FSM/EpsilonNFA.cpp
@@ -266,16 +266,25 @@ bool EpsilonNFA::isTotal() const {
 }
 
 int EpsilonNFA::compare(const EpsilonNFA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	std::compare<decltype(states)> comp;
+	int res = comp(states, other.states);
+	if(res == 0) {
+		std::compare<decltype(inputAlphabet)> comp;
+		res = comp(inputAlphabet, other.inputAlphabet);
 	}
+	if(res == 0) {
+		std::compare<decltype(initialState)> comp;
+		res = comp(initialState, other.initialState);
+	}
+	if(res == 0) {
+		std::compare<decltype(finalStates)> comp;
+		res = comp(finalStates, other.finalStates);
+	}
+	if(res == 0) {
+		std::compare<decltype(transitions)> comp;
+		res = comp(transitions, other.transitions);
+	}
+	return res;
 }
 
 void EpsilonNFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.cpp b/alib2data/src/automaton/FSM/ExtendedNFA.cpp
index 663920663a37efd73da99f2c3df1f5cd5fecf2a2..3d7d13dfaf582d60663c3f322cb8fdb9192c289a 100644
--- a/alib2data/src/automaton/FSM/ExtendedNFA.cpp
+++ b/alib2data/src/automaton/FSM/ExtendedNFA.cpp
@@ -177,16 +177,25 @@ std::map<std::pair<State, regexp::RegExp>, std::set<State> > ExtendedNFA::getTra
 }
 
 int ExtendedNFA::compare(const ExtendedNFA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	std::compare<decltype(states)> comp;
+	int res = comp(states, other.states);
+	if(res == 0) {
+		std::compare<decltype(inputAlphabet)> comp;
+		res = comp(inputAlphabet, other.inputAlphabet);
 	}
+	if(res == 0) {
+		std::compare<decltype(initialState)> comp;
+		res = comp(initialState, other.initialState);
+	}
+	if(res == 0) {
+		std::compare<decltype(finalStates)> comp;
+		res = comp(finalStates, other.finalStates);
+	}
+	if(res == 0) {
+		std::compare<decltype(transitions)> comp;
+		res = comp(transitions, other.transitions);
+	}
+	return res;
 }
 
 void ExtendedNFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp b/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
index fbe13322e8cb40d3f0cf3b59f356a1452ff5f275..4b505cb25ab503eba25cd061566955f905eb5a82 100644
--- a/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
+++ b/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
@@ -156,16 +156,25 @@ unsigned MultiInitialStateNFA::transitionsSize() const {
 }
 
 int MultiInitialStateNFA::compare(const MultiInitialStateNFA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, transitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.transitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	std::compare<decltype(states)> comp;
+	int res = comp(states, other.states);
+	if(res == 0) {
+		std::compare<decltype(inputAlphabet)> comp;
+		res = comp(inputAlphabet, other.inputAlphabet);
 	}
+	if(res == 0) {
+		std::compare<decltype(initialStates)> comp;
+		res = comp(initialStates, other.initialStates);
+	}
+	if(res == 0) {
+		std::compare<decltype(finalStates)> comp;
+		res = comp(finalStates, other.finalStates);
+	}
+	if(res == 0) {
+		std::compare<decltype(transitions)> comp;
+		res = comp(transitions, other.transitions);
+	}
+	return res;
 }
 
 void MultiInitialStateNFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/FSM/NFA.cpp b/alib2data/src/automaton/FSM/NFA.cpp
index 72ee67a7facba93aafdec6ef2e3dd4a869984a21..f9df9181e96c03565d551be8e069206773dc8fbd 100644
--- a/alib2data/src/automaton/FSM/NFA.cpp
+++ b/alib2data/src/automaton/FSM/NFA.cpp
@@ -139,16 +139,25 @@ unsigned NFA::transitionsSize() const {
 }
 
 int NFA::compare(const NFA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialState, finalStates, transitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.transitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	std::compare<decltype(states)> comp;
+	int res = comp(states, other.states);
+	if(res == 0) {
+		std::compare<decltype(inputAlphabet)> comp;
+		res = comp(inputAlphabet, other.inputAlphabet);
 	}
+	if(res == 0) {
+		std::compare<decltype(initialState)> comp;
+		res = comp(initialState, other.initialState);
+	}
+	if(res == 0) {
+		std::compare<decltype(finalStates)> comp;
+		res = comp(finalStates, other.finalStates);
+	}
+	if(res == 0) {
+		std::compare<decltype(transitions)> comp;
+		res = comp(transitions, other.transitions);
+	}
+	return res;
 }
 
 void NFA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/DPDA.cpp b/alib2data/src/automaton/PDA/DPDA.cpp
index 85bd138fe4e22d020d7911c0fa93854215ff31b7..2b16f016c8519f52cfd750017b04fd21562adb00 100644
--- a/alib2data/src/automaton/PDA/DPDA.cpp
+++ b/alib2data/src/automaton/PDA/DPDA.cpp
@@ -223,16 +223,33 @@ std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std:
 }
 
 int DPDA::compare(const DPDA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialState, finalStates, stackAlphabet, initialSymbol, transitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.initialSymbol, other.transitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	std::compare<decltype(states)> comp;
+	int res = comp(states, other.states);
+	if(res == 0) {
+		std::compare<decltype(inputAlphabet)> comp;
+		res = comp(inputAlphabet, other.inputAlphabet);
+	}
+	if(res == 0) {
+		std::compare<decltype(initialState)> comp;
+		res = comp(initialState, other.initialState);
+	}
+	if(res == 0) {
+		std::compare<decltype(finalStates)> comp;
+		res = comp(finalStates, other.finalStates);
+	}
+	if(res == 0) {
+		std::compare<decltype(stackAlphabet)> comp;
+		res = comp(stackAlphabet, other.stackAlphabet);
+	}
+	if(res == 0) {
+		std::compare<decltype(initialSymbol)> comp;
+		res = comp(initialSymbol, other.initialSymbol);
+	}
+	if(res == 0) {
+		std::compare<decltype(transitions)> comp;
+		res = comp(transitions, other.transitions);
 	}
+	return res;
 }
 
 void DPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp b/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp
index c6fa402b502d1155e6fa5b4e76a0856622369644..8f263d6f7d008b50aeaeaafed9d345cbef9b786c 100644
--- a/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp
+++ b/alib2data/src/automaton/PDA/InputDrivenNPDA.cpp
@@ -175,16 +175,37 @@ bool InputDrivenNPDA::isDeterministic() const {
 }
 
 int InputDrivenNPDA::compare(const InputDrivenNPDA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, transitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.transitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	std::compare<decltype(states)> comp;
+	int res = comp(states, other.states);
+	if(res == 0) {
+		std::compare<decltype(inputAlphabet)> comp;
+		res = comp(inputAlphabet, other.inputAlphabet);
+	}
+	if(res == 0) {
+		std::compare<decltype(initialStates)> comp;
+		res = comp(initialStates, other.initialStates);
+	}
+	if(res == 0) {
+		std::compare<decltype(finalStates)> comp;
+		res = comp(finalStates, other.finalStates);
+	}
+	if(res == 0) {
+		std::compare<decltype(stackAlphabet)> comp;
+		res = comp(stackAlphabet, other.stackAlphabet);
+	}
+	if(res == 0) {
+		std::compare<decltype(initialSymbol)> comp;
+		res = comp(initialSymbol, other.initialSymbol);
+	}
+	if(res == 0) {
+		std::compare<decltype(inputSymbolToPushdownStoreOperation)> comp;
+		res = comp(inputSymbolToPushdownStoreOperation, other.inputSymbolToPushdownStoreOperation);
+	}
+	if(res == 0) {
+		std::compare<decltype(transitions)> comp;
+		res = comp(transitions, other.transitions);
 	}
+	return res;
 }
 
 void InputDrivenNPDA::operator>>(std::ostream& out) const {
@@ -193,7 +214,10 @@ void InputDrivenNPDA::operator>>(std::ostream& out) const {
 		<< " inputAlphabet = " << inputAlphabet
 		<< " initialStates = " << initialStates
 		<< " finalStates = " << finalStates
+		<< " stackAlphabet = " << stackAlphabet
+		<< " initialSymbol = " << initialSymbol
 		<< " transitions = " << transitions
+		<< " inputSymbolToPushdownStoreOperation = " << inputSymbolToPushdownStoreOperation
 		<< ")";
 }
 
diff --git a/alib2data/src/automaton/PDA/NPDA.cpp b/alib2data/src/automaton/PDA/NPDA.cpp
index 5407aaaed8f383459325dfe14df9fa5c54b356ae..a95026b83b318de8dc2d2317c02731c5bc65b900 100644
--- a/alib2data/src/automaton/PDA/NPDA.cpp
+++ b/alib2data/src/automaton/PDA/NPDA.cpp
@@ -134,16 +134,33 @@ const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>
 }
 
 int NPDA::compare(const NPDA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialStates, finalStates, stackAlphabet, initialSymbols, transitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialStates, other.finalStates, other.stackAlphabet, other.initialSymbols, other.transitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	std::compare<decltype(states)> comp;
+	int res = comp(states, other.states);
+	if(res == 0) {
+		std::compare<decltype(inputAlphabet)> comp;
+		res = comp(inputAlphabet, other.inputAlphabet);
+	}
+	if(res == 0) {
+		std::compare<decltype(initialStates)> comp;
+		res = comp(initialStates, other.initialStates);
+	}
+	if(res == 0) {
+		std::compare<decltype(finalStates)> comp;
+		res = comp(finalStates, other.finalStates);
+	}
+	if(res == 0) {
+		std::compare<decltype(stackAlphabet)> comp;
+		res = comp(stackAlphabet, other.stackAlphabet);
+	}
+	if(res == 0) {
+		std::compare<decltype(initialSymbols)> comp;
+		res = comp(initialSymbols, other.initialSymbols);
+	}
+	if(res == 0) {
+		std::compare<decltype(transitions)> comp;
+		res = comp(transitions, other.transitions);
 	}
+	return res;
 }
 
 void NPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp
index 0b44a8fafba36597dd97bd62d9eebb74b9764ab7..453c9b3a34251d473c20c0bbdd29aa155f6bebf8 100644
--- a/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp
+++ b/alib2data/src/automaton/PDA/RealTimeHeightDeterministicDPDA.cpp
@@ -367,16 +367,41 @@ const std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol>>
 }
 
 int RealTimeHeightDeterministicDPDA::compare(const RealTimeHeightDeterministicDPDA& other) const {
-	auto first = std::tie(states, inputAlphabet, initialState, finalStates, stackAlphabet, bottomOfTheStackSymbol, callTransitions, returnTransitions, localTransitions);
-	auto second = std::tie(other.states, other.inputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.bottomOfTheStackSymbol, other.callTransitions, other.returnTransitions, other.localTransitions);
-
-	if(first == second) {
-		return 0;
-	} else if(first < second) {
-		return -1;
-	} else {
-		return 1;
+	std::compare<decltype(states)> comp;
+	int res = comp(states, other.states);
+	if(res == 0) {
+		std::compare<decltype(inputAlphabet)> comp;
+		res = comp(inputAlphabet, other.inputAlphabet);
+	}
+	if(res == 0) {
+		std::compare<decltype(initialState)> comp;
+		res = comp(initialState, other.initialState);
+	}
+	if(res == 0) {
+		std::compare<decltype(finalStates)> comp;
+		res = comp(finalStates, other.finalStates);
+	}
+	if(res == 0) {
+		std::compare<decltype(stackAlphabet)> comp;
+		res = comp(stackAlphabet, other.stackAlphabet);
+	}
+	if(res == 0) {
+		std::compare<decltype(bottomOfTheStackSymbol)> comp;
+		res = comp(bottomOfTheStackSymbol, other.bottomOfTheStackSymbol);
+	}
+	if(res == 0) {
+		std::compare<decltype(callTransitions)> comp;
+		res = comp(callTransitions, other.callTransitions);
+	}
+	if(res == 0) {
+		std::compare<decltype(returnTransitions)> comp;
+		res = comp(returnTransitions, other.returnTransitions);
+	}
+	if(res == 0) {
+		std::compare<decltype(localTransitions)> comp;
+		res = comp(localTransitions, other.localTransitions);
 	}
+	return res;
 }
 
 void RealTimeHeightDeterministicDPDA::operator>>(std::ostream& out) const {
diff --git a/alib2data/src/std/compare.hpp b/alib2data/src/std/compare.hpp
index fbb2a3dbe46f53336edf1b9be25a8910b543e6cb..8d8741a658373b6e3f7d6031f786c73fac355532 100644
--- a/alib2data/src/std/compare.hpp
+++ b/alib2data/src/std/compare.hpp
@@ -12,6 +12,7 @@
 #include <vector>
 #include <string>
 #include <map>
+#include <tuple>
 
 namespace std {
 
@@ -91,6 +92,35 @@ struct compare<map<T, R>> {
 	}
 };
 
+template<int I, typename Tuple>
+struct compareTupleHelper;
+
+template<int I, typename Tuple>
+struct compareTupleHelper {
+	static int compHelp(const Tuple& t1, const Tuple& t2) {
+		compare<typename tuple_element<I, Tuple>::type> comp;
+		int res = comp(std::get<I>(t1), std::get<I>(t2));
+		if(res != 0) return res;
+		return compareTupleHelper<I - 1, Tuple>::compHelp(t1, t2);
+	}
+};
+
+template<class Tuple>
+struct compareTupleHelper<0, Tuple> {
+	static int compHelp(const Tuple& t1, const Tuple& t2) {
+		compare<typename tuple_element<0, Tuple>::type> comp;
+		return comp(std::get<0>(t1), std::get<0>(t2));
+	}
+};
+
+
+template<typename ... Ts>
+struct compare<tuple<Ts...>> {
+	int operator()(const tuple<Ts...>& first, const tuple<Ts...>& second) const {
+		return compareTupleHelper<tuple_size<std::tuple<Ts...>>::value - 1, std::tuple<Ts...>>::compHelp(first, second);
+	}
+};
+
 template<>
 struct compare<string> {
 	int operator()(const string& first, const string& second) const {
diff --git a/alib2data/src/std/variant.hpp b/alib2data/src/std/variant.hpp
index fc19fc4e4e1b82d3cff460b40323c5079f5fcee0..182f7260b6dd17a9029391ed8b5272ddbb8ab17b 100644
--- a/alib2data/src/std/variant.hpp
+++ b/alib2data/src/std/variant.hpp
@@ -13,6 +13,7 @@
 #include <typeinfo>
 #include "type_traits.hpp"
 #include <string>
+#include "compare.hpp"
 
 namespace std {
 
@@ -94,6 +95,17 @@ struct variant_helper<F, Ts...> {
 			return variant_helper<Ts...>::compareLess(this_t, this_v, other_t, other_v);
 	}
 
+	inline static int compareHelper(size_t this_t, const void * this_v, size_t other_t, const void * other_v)
+	{
+		if (this_t == typeid(F).hash_code() && other_t != typeid(F).hash_code()) return -1;
+		if (this_t != typeid(F).hash_code() && other_t == typeid(F).hash_code()) return 1;
+
+		if (this_t == typeid(F).hash_code() && other_t == typeid(F).hash_code()) {
+			compare<F> comp;
+			return comp( *(reinterpret_cast<const F*>(this_v)), *(reinterpret_cast<const F*>(other_v)));
+		} else
+			return variant_helper<Ts...>::compareHelper(this_t, this_v, other_t, other_v);
+	}
 };
 
 template<> struct variant_helper<>  {
@@ -104,6 +116,7 @@ inline static bool compareEq(size_t, const void *, size_t, const void *) { retur
 inline static void print(ostream&, const size_t, const void *) {}
 inline static std::string string(const size_t, const void *) { return ""; }
 inline static bool compareLess(size_t, const void *, size_t, const void *) { return false; }
+inline static int compareHelper(size_t, const void *, size_t, const void *) { return 0; }
 };
 
 template<typename ST, typename AT, typename... Ts>
@@ -195,6 +208,11 @@ public:
 		return !(*this < other);
 	}
 
+	int compare(const variant<F, Ts...>& other) const
+	{
+		return helper_t::compareHelper(this->type_id, &this->data, other.type_id, &other.data);
+	}
+
 	template<typename T>
 	bool is() const {
 		return (this->type_id == typeid(T).hash_code());
@@ -256,6 +274,13 @@ public:
 	}
 };
 
+template<typename ... Ts>
+struct compare<variant<Ts...>> {
+	int operator()(const variant<Ts...>& first, const variant<Ts...>& second) {
+		return first.compare(second);
+	}
+};
+
 } /* namespace std */
 
 #endif