From 656ba0f0d51075dfa55ea90e7bef6380865ac780 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Sun, 28 Sep 2014 20:53:02 +0200
Subject: [PATCH] add RHDPDA determinisation

---
 adeterminize2/src/adeterminize.cpp            |   6 +-
 .../src/determinize/common/RHDPDACommon.cpp   | 223 ++++++++++++++++
 .../src/determinize/common/RHDPDACommon.h     |  43 +++
 .../determinize/hdpda/HDPDADeterminizer.cpp   | 244 ++++++++++++++++++
 .../src/determinize/hdpda/HDPDADeterminizer.h |  24 ++
 .../src/determinize/vpa/VPADeterminizer.cpp   | 171 ++----------
 .../src/determinize/vpa/VPADeterminizer.h     |   7 -
 7 files changed, 553 insertions(+), 165 deletions(-)
 create mode 100644 alib2algo/src/determinize/common/RHDPDACommon.cpp
 create mode 100644 alib2algo/src/determinize/common/RHDPDACommon.h
 create mode 100644 alib2algo/src/determinize/hdpda/HDPDADeterminizer.cpp
 create mode 100644 alib2algo/src/determinize/hdpda/HDPDADeterminizer.h

diff --git a/adeterminize2/src/adeterminize.cpp b/adeterminize2/src/adeterminize.cpp
index 126f52b603..d557456be8 100644
--- a/adeterminize2/src/adeterminize.cpp
+++ b/adeterminize2/src/adeterminize.cpp
@@ -13,6 +13,7 @@
 #include "determinize/nfa/NFADeterminizer.h"
 #include "determinize/idpda/IDPDADeterminizer.h"
 #include "determinize/vpa/VPADeterminizer.h"
+#include "determinize/hdpda/HDPDADeterminizer.h"
 #include "automaton/PDAToRHPDA.h"
 #include "automaton/RHPDAToPDA.h"
 
@@ -116,8 +117,9 @@ int main(int argc, char** argv) {
 		} else if (type == TYPE_RHDPDA) {
 			automaton::NPDA npda = alib::DataFactory::fromTokens<automaton::NPDA>(tokens);
 			automaton::RealTimeHeightDeterministicNPDA rhpda = automaton::PDAToRHPDA::convert(npda);
-			automaton::NPDA npda2 = automaton::RHPDAToPDA::convert(rhpda);
-			alib::DataFactory::toStdout(npda2);
+			automaton::RealTimeHeightDeterministicNPDA dpda = determinize::HDPDADeterminizer::determinize(rhpda);
+			automaton::NPDA dpda2 = automaton::RHPDAToPDA::convert(dpda);
+			alib::DataFactory::toStdout(dpda2);
 			return 0;
 		}
 
diff --git a/alib2algo/src/determinize/common/RHDPDACommon.cpp b/alib2algo/src/determinize/common/RHDPDACommon.cpp
new file mode 100644
index 0000000000..00dbd3b3c0
--- /dev/null
+++ b/alib2algo/src/determinize/common/RHDPDACommon.cpp
@@ -0,0 +1,223 @@
+#include "RHDPDACommon.h"
+#include "label/LabelPairLabel.h"
+#include "label/LabelSetLabel.h"
+#include "label/ObjectLabel.h"
+#include "object/Object.h"
+#include "alphabet/LabeledSymbol.h"
+
+#include "automaton/PDA/VisiblyPushdownNPDA.h"
+#include "automaton/PDA/RealTimeHeightDeterministicNPDA.h"
+
+namespace determinize {
+
+label::Label packToStateLabel(std::set<std::pair<label::Label, label::Label>>&& data) {
+	std::set<label::Label> res;
+	for(auto&& subData : std::move(data)) {
+		res.insert(label::Label(label::LabelPairLabel(std::move(subData))));
+	}
+	return label::Label(label::LabelSetLabel(std::move(res)));
+}
+
+std::set<std::pair<label::Label, label::Label>> unpackFromStateLabel(const label::Label& data) {
+	std::set<std::pair<label::Label, label::Label>> res;
+	const std::set<label::Label>& labelSet = static_cast<const label::LabelSetLabel&>(data.getData()).getData();
+	for (const auto& subData : labelSet) {
+		const std::pair<label::Label, label::Label>& labelPair = static_cast<const label::LabelPairLabel&>(subData.getData()).getData();
+		res.insert(labelPair);
+	}
+	return res;
+}
+
+label::Label packToStackSymbolLabel(std::pair<std::set<std::pair<label::Label, label::Label>>, alphabet::Symbol>&& data) {
+	label::Label res1 = packToStateLabel(std::move(data.first));
+	label::Label res2 = label::Label(label::ObjectLabel(alib::Object(std::move(data.second.getData()))));
+	return label::Label(label::LabelPairLabel(std::make_pair(std::move(res1), std::move(res2))));
+}
+
+std::pair<std::set<std::pair<label::Label, label::Label>>, alphabet::Symbol> unpackFromDVPAStackSymbolLabel(const label::Label& data) {
+	const label::Label& labelPairFirst = static_cast<const label::LabelPairLabel&>(data.getData()).getData().first;
+	std::set<std::pair<label::Label, label::Label>> res = unpackFromStateLabel(labelPairFirst);
+
+	const label::Label& labelPairSecond = static_cast<const label::LabelPairLabel&>(data.getData()).getData().second;
+	const alib::Object& object = static_cast<const label::ObjectLabel&>(labelPairSecond.getData()).getData();
+	return std::make_pair(std::move(res), alphabet::Symbol(static_cast<const alphabet::SymbolBase&>(object.getData())));
+}
+
+label::Label packToStackSymbolLabel(std::pair<std::set<std::pair<label::Label, label::Label>>, std::variant<string::Epsilon, alphabet::Symbol>>&& data) {
+	label::Label res1 = packToStateLabel(std::move(data.first));
+	if(data.second.is<string::Epsilon>()) {
+		label::Label res2 = label::Label(label::ObjectLabel(alib::Object(std::move(data.second.get<string::Epsilon>()))));
+		return label::Label(label::LabelPairLabel(std::make_pair(std::move(res1), std::move(res2))));
+	} else {
+		label::Label res2 = label::Label(label::ObjectLabel(alib::Object(std::move(data.second.get<alphabet::Symbol>().getData()))));
+		return label::Label(label::LabelPairLabel(std::make_pair(std::move(res1), std::move(res2))));
+	}
+}
+
+std::pair<std::set<std::pair<label::Label, label::Label>>, std::variant<string::Epsilon, alphabet::Symbol>> unpackFromDRHDPDAStackSymbolLabel(const label::Label& data) {
+	const label::Label& labelPairFirst = static_cast<const label::LabelPairLabel&>(data.getData()).getData().first;
+	std::set<std::pair<label::Label, label::Label>> res = unpackFromStateLabel(labelPairFirst);
+
+	const label::Label& labelPairSecond = static_cast<const label::LabelPairLabel&>(data.getData()).getData().second;
+	const alib::Object& object = static_cast<const label::ObjectLabel&>(labelPairSecond.getData()).getData();
+	if(object.getData() == string::Epsilon::EPSILON) {
+		return std::make_pair(std::move(res), std::variant<string::Epsilon, alphabet::Symbol>(static_cast<const string::Epsilon&>(object.getData())));
+	} else {
+		return std::make_pair(std::move(res), std::variant<string::Epsilon, alphabet::Symbol>(alphabet::Symbol(static_cast<const alphabet::SymbolBase&>(object.getData()))));
+	}
+}
+
+std::set<label::Label> retrieveDSubSet(const std::set<std::pair<label::Label, label::Label>>& localOperation) {
+	std::set<label::Label> id;
+	for(const auto& entry : localOperation) {
+		id.insert(entry.second);
+	}
+	return id;
+}
+
+std::set<std::pair<label::Label, label::Label>> createIdentity(std::set<label::Label>&& states) {
+	std::set<std::pair<label::Label, label::Label>> id;
+	for(const label::Label& state : states) {
+		id.insert(std::make_pair(state, state));
+	}
+	return id;
+}
+
+template<class T>
+const automaton::State* existsDirtyState(const T& d, const T& n) {
+	for(const automaton::State& state : d.getStates()) {
+		const label::Label& stateLabel = state.getName();
+		const std::set<label::Label> dSubSet = retrieveDSubSet(unpackFromStateLabel(stateLabel));
+
+		bool originalCallsLocals = false;
+		for(const auto& transition : n.getCallTransitions()) {
+			if(dSubSet.count(transition.first.first.getName())) {
+				originalCallsLocals = true;
+				break;
+			}
+		}
+		for(const auto& transition : n.getLocalTransitions()) {
+			if(dSubSet.count(transition.first.first.getName())) {
+				originalCallsLocals = true;
+				break;
+			}
+		}
+
+		if(!originalCallsLocals) continue;
+
+		for(const auto& transition : d.getCallTransitions()) {
+			if(stateLabel != transition.first.first.getName()) continue;
+
+			goto continue2;
+		}
+		for(const auto& transition : d.getLocalTransitions()) {
+			if(stateLabel != transition.first.first.getName()) continue;
+
+			goto continue2;
+		}
+		return &state;
+
+continue2: while(false); //TODO remove this
+	}
+	return NULL;
+}
+
+template const automaton::State* existsDirtyState(const automaton::VisiblyPushdownNPDA& d, const automaton::VisiblyPushdownNPDA& n);
+template const automaton::State* existsDirtyState(const automaton::RealTimeHeightDeterministicNPDA& d, const automaton::RealTimeHeightDeterministicNPDA& n);
+
+template<class T>
+void localClosure(std::set<label::Label>& states, const std::set<label::Label>& oldStates, const T& d) {
+	std::set<label::Label> newStates;
+
+	for(const label::Label& state : oldStates) {
+		for(const auto& transition : d.getLocalTransitions()) {
+			if(transition.second.begin()->getName() != state) continue;
+
+			if(!states.count(transition.first.first.getName())) {
+				states.insert(transition.first.first.getName());
+				newStates.insert(transition.first.first.getName());
+			}
+		}
+
+		for(const auto& transition : d.getReturnTransitions()) {
+			if(transition.second.begin()->getName() != state) continue;
+
+			const alphabet::Symbol& popSymbol = std::get<2>(transition.first);
+			if(popSymbol == d.getBottomOfTheStackSymbol()) continue;
+			const label::Label& popSymbolLabel = static_cast<const alphabet::LabeledSymbol&>(popSymbol.getData()).getLabel();
+			const label::Label& statePart = static_cast<const label::LabelPairLabel&>(popSymbolLabel.getData()).getData().first;
+
+			if(!states.count(statePart)) {
+				states.insert(statePart);
+				newStates.insert(statePart);
+			}
+		}
+	}
+
+	if(newStates.empty()) return;
+	localClosure(states, newStates, d);
+}
+
+template void localClosure(std::set<label::Label>& states, const std::set<label::Label>& oldStates, const automaton::VisiblyPushdownNPDA& d);
+template void localClosure(std::set<label::Label>& states, const std::set<label::Label>& oldStates, const automaton::RealTimeHeightDeterministicNPDA& d);
+
+template<class T>
+std::pair<automaton::State, alphabet::Symbol>* existsDirtyStateSymbol(const T& d, const T& n) {
+	for(const automaton::State& state : d.getStates()) {
+		const label::Label& stateLabel = state.getName();
+
+		std::set<label::Label> lc { stateLabel };
+		localClosure(lc, std::set<label::Label>{stateLabel}, d); //intentional copy
+
+		bool originalPops = false;
+		for(const label::Label& localState : lc) {
+			const std::set<label::Label> dSubSet = retrieveDSubSet(unpackFromStateLabel(localState));
+
+			for(const auto& transition : n.getReturnTransitions()) {
+				if(dSubSet.count(std::get<0>(transition.first).getName())) {
+					originalPops = true;
+					goto break2;
+				}
+			}
+		}
+break2: while(false);
+		if(!originalPops) continue;
+
+		std::set<alphabet::Symbol> topSymbols;
+		for(const label::Label& localState : lc) {
+			for(const auto& transition : d.getCallTransitions()) {
+				for(const auto& to : transition.second) {
+					if(localState != to.first.getName()) continue;
+
+					topSymbols.insert(to.second);
+				}
+			}
+
+			if(d.getInitialStates().begin()->getName() == localState) {
+				topSymbols.insert(d.getBottomOfTheStackSymbol());
+			}
+		}
+
+		for(const auto& transition : d.getReturnTransitions()) {
+			if(stateLabel != std::get<0>(transition.first).getName()) continue;
+
+			topSymbols.erase(std::get<2>(transition.first));
+		}
+
+		if(!topSymbols.empty()) return new std::pair<automaton::State, alphabet::Symbol>(automaton::State(stateLabel), *topSymbols.begin());
+	}
+	return NULL;
+}
+
+template std::pair<automaton::State, alphabet::Symbol>* existsDirtyStateSymbol(const automaton::VisiblyPushdownNPDA& d, const automaton::VisiblyPushdownNPDA& n);
+template std::pair<automaton::State, alphabet::Symbol>* existsDirtyStateSymbol(const automaton::RealTimeHeightDeterministicNPDA& d, const automaton::RealTimeHeightDeterministicNPDA& n);
+
+std::set<label::Label> retrieveLabels(const std::set<automaton::State>& states) {
+	std::set<label::Label> labels;
+	for(const automaton::State& state : states) {
+		labels.insert(state.getName());
+	}
+	return labels;
+}
+
+} /* namespace determinize */
diff --git a/alib2algo/src/determinize/common/RHDPDACommon.h b/alib2algo/src/determinize/common/RHDPDACommon.h
new file mode 100644
index 0000000000..765306ab46
--- /dev/null
+++ b/alib2algo/src/determinize/common/RHDPDACommon.h
@@ -0,0 +1,43 @@
+#ifndef RHDPDA_VPA_COMMON_H_
+#define RHDPDA_VPA_COMMON_H_
+
+#include "label/Label.h"
+#include "automaton/common/State.h"
+#include "alphabet/Symbol.h"
+#include "string/Epsilon.h"
+#include "std/variant.hpp"
+#include <set>
+#include <map>
+
+namespace determinize {
+
+label::Label packToStateLabel(std::set<std::pair<label::Label, label::Label>>&& data);
+
+std::set<std::pair<label::Label, label::Label>> unpackFromStateLabel(const label::Label& data);
+
+label::Label packToStackSymbolLabel(std::pair<std::set<std::pair<label::Label, label::Label>>, alphabet::Symbol>&& data);
+
+std::pair<std::set<std::pair<label::Label, label::Label>>, alphabet::Symbol> unpackFromDVPAStackSymbolLabel(const label::Label& data);
+
+label::Label packToStackSymbolLabel(std::pair<std::set<std::pair<label::Label, label::Label>>, std::variant<string::Epsilon, alphabet::Symbol>>&& data);
+
+std::pair<std::set<std::pair<label::Label, label::Label>>, std::variant<string::Epsilon, alphabet::Symbol>> unpackFromDRHDPDAStackSymbolLabel(const label::Label& data);
+
+std::set<label::Label> retrieveDSubSet(const std::set<std::pair<label::Label, label::Label>>& localOperation);
+
+std::set<std::pair<label::Label, label::Label>> createIdentity(std::set<label::Label>&& states);
+
+template<class T>
+const automaton::State* existsDirtyState(const T& d, const T& n);
+
+template<class T>
+void localClosure(std::set<label::Label>& states, const std::set<label::Label>& oldStates, const T& d);
+
+template<class T>
+std::pair<automaton::State, alphabet::Symbol>* existsDirtyStateSymbol(const T& d, const T& n);
+
+std::set<label::Label> retrieveLabels(const std::set<automaton::State>& states);
+
+} /* namespace determinize */
+
+#endif /* RHDPDA_VPA_COMMON_H_ */
diff --git a/alib2algo/src/determinize/hdpda/HDPDADeterminizer.cpp b/alib2algo/src/determinize/hdpda/HDPDADeterminizer.cpp
new file mode 100644
index 0000000000..cde68385e7
--- /dev/null
+++ b/alib2algo/src/determinize/hdpda/HDPDADeterminizer.cpp
@@ -0,0 +1,244 @@
+#include "HDPDADeterminizer.h"
+#include "../common/RHDPDACommon.h"
+
+#include "automaton/common/State.h"
+#include "alphabet/Symbol.h"
+#include "alphabet/LabeledSymbol.h"
+#include "label/Label.h"
+#include "exception/AlibException.h"
+#include <std/set.hpp>
+#include <iostream>
+
+namespace determinize {
+
+void addRetTransition(const automaton::State& from, const std::variant<string::Epsilon, alphabet::Symbol>& input, const alphabet::Symbol& dvpdaSymbol, const automaton::State& to, automaton::RealTimeHeightDeterministicNPDA& deterministic) {
+	deterministic.addState(from);
+	deterministic.addState(to);
+	deterministic.addStackSymbol(dvpdaSymbol);
+	
+	deterministic.addReturnTransition(from, input, dvpdaSymbol, to);
+}
+
+void retInitial(const automaton::State& state, const alphabet::Symbol& pdaSymbol, const std::variant<string::Epsilon, alphabet::Symbol>& input, const automaton::RealTimeHeightDeterministicNPDA& nondeterministic, automaton::RealTimeHeightDeterministicNPDA& deterministic) {
+	std::set<std::pair<label::Label, label::Label>> S = unpackFromStateLabel(state.getName());
+
+	std::set<std::pair<label::Label, label::Label>> S1;
+	for(const auto& entry : S) {
+		const label::Label& q = entry.first;
+		const label::Label& q2 = entry.second;
+
+		for(const auto& transition : nondeterministic.getReturnTransitions()) {
+			if(q2 != std::get<0>(transition.first).getName()) continue;
+			if(input != std::get<1>(transition.first)) continue;
+			if(nondeterministic.getBottomOfTheStackSymbol() != std::get<2>(transition.first)) continue;
+
+			for(const auto& to : transition.second) {
+				const label::Label& q1 = to.getName();
+				S1.insert(std::make_pair(q, q1));
+			}
+		}
+	}
+
+	addRetTransition(state, input, pdaSymbol, automaton::State(packToStateLabel(std::move(S1))), deterministic);
+}
+
+void ret(const automaton::State& state, const alphabet::Symbol& pdaSymbol, const std::variant<string::Epsilon, alphabet::Symbol>& input, const automaton::RealTimeHeightDeterministicNPDA& nondeterministic, automaton::RealTimeHeightDeterministicNPDA& deterministic) {
+	std::set<std::pair<label::Label, label::Label>> S = unpackFromStateLabel(state.getName());
+	std::pair<std::set<std::pair<label::Label, label::Label>>, std::variant<string::Epsilon, alphabet::Symbol>> pdaSymbolUnpack = unpackFromDRHDPDAStackSymbolLabel(static_cast<const alphabet::LabeledSymbol&>(pdaSymbol.getData()).getLabel());
+	const std::set<std::pair<label::Label, label::Label>>& S1 = pdaSymbolUnpack.first;
+
+	std::set<std::pair<label::Label, label::Label>> update;
+
+	for(const auto& transition : nondeterministic.getCallTransitions()) {
+		if(pdaSymbolUnpack.second != std::get<1>(transition.first)) continue;
+
+		const label::Label& q = std::get<0>(transition.first).getName();
+		for(const auto& to : transition.second) {
+			const label::Label q1 = to.first.getName();
+			const alphabet::Symbol& gamma = to.second;
+
+			for(const auto& entry : S) {
+				if(q1 != entry.first) continue;
+				const label::Label& q2 = entry.second;
+
+				for(const auto& transition2 : nondeterministic.getReturnTransitions()) {
+					if(q2 != std::get<0>(transition2.first).getName()) continue;
+					if(input != std::get<1>(transition2.first)) continue;
+					if(gamma != std::get<2>(transition2.first)) continue;
+
+					for(const auto& to2 : transition2.second) {
+						const label::Label& qI = to2.getName();
+
+						update.insert(std::make_pair(q, qI));
+					}
+				}
+			}
+		}
+	}
+
+	std::set<std::pair<label::Label, label::Label>> S2;
+	for(const auto& entry : S1) {
+		const label::Label& q = entry.first;
+		const label::Label& q3 = entry.second;
+		for(const auto& entry2 : update) {
+			if(q3 != entry2.first) continue;
+
+			const label::Label& qI = entry2.second;
+
+			S2.insert(std::make_pair(q, qI));
+		}
+	}
+
+	addRetTransition(state, input, pdaSymbol, automaton::State(packToStateLabel(std::move(S2))), deterministic);
+}
+
+void addCallTransition(const automaton::State& from, const std::variant<string::Epsilon, alphabet::Symbol>& input, const automaton::State& to, const alphabet::Symbol& dvpdaSymbol, automaton::RealTimeHeightDeterministicNPDA& deterministic) {
+	deterministic.addState(from);
+	deterministic.addState(to);
+	deterministic.addStackSymbol(dvpdaSymbol);
+
+	deterministic.addCallTransition(from, input, to, dvpdaSymbol);
+}
+
+void call(const automaton::State& state, const std::variant<string::Epsilon, alphabet::Symbol>& input, const automaton::RealTimeHeightDeterministicNPDA& nondeterministic, automaton::RealTimeHeightDeterministicNPDA& deterministic) {
+	std::set<std::pair<label::Label, label::Label>> S = unpackFromStateLabel(state.getName());
+
+	std::set<label::Label> R = retrieveDSubSet(S);
+	std::set<label::Label> R1;
+
+	for(const label::Label& q : R) {
+		for(const auto& transition : nondeterministic.getCallTransitions()) {
+			if(q != transition.first.first.getName()) continue;
+			if(input != transition.first.second) continue;
+
+			for(const auto& to : transition.second) {
+				const label::Label& q1 = to.first.getName();
+
+				R1.insert(q1);
+			}
+		}
+	}
+
+	addCallTransition(state, input, automaton::State(packToStateLabel(createIdentity(std::move(R1)))), alphabet::Symbol(alphabet::LabeledSymbol(packToStackSymbolLabel(std::make_pair(std::move(S), input)))), deterministic);
+}
+
+void addLocalTransition(const automaton::State& from, const std::variant<string::Epsilon, alphabet::Symbol>& input, const automaton::State& to, automaton::RealTimeHeightDeterministicNPDA& deterministic) {
+	deterministic.addState(from);
+	deterministic.addState(to);
+
+	deterministic.addLocalTransition(from, input, to);
+}
+
+void local(const automaton::State& state, const std::variant<string::Epsilon, alphabet::Symbol>& input, const automaton::RealTimeHeightDeterministicNPDA& nondeterministic, automaton::RealTimeHeightDeterministicNPDA& deterministic) {
+	std::set<std::pair<label::Label, label::Label>> S = unpackFromStateLabel(state.getName());
+	std::set<std::pair<label::Label, label::Label>> S1;
+
+	for(const auto& entry : S) {
+		label::Label q = entry.first;
+		label::Label q2 = entry.second;
+		for(const auto& transition : nondeterministic.getLocalTransitions()) {
+			if(q2 != transition.first.first.getName()) continue;
+			if(input != transition.first.second) continue;
+
+			for(const auto& to : transition.second) {
+				label::Label q1 = to.getName();
+
+				S1.insert(std::make_pair(q, q1));
+			}
+		}
+	}
+	
+	addLocalTransition(state, input, automaton::State(packToStateLabel(std::move(S1))), deterministic);
+}
+
+std::tuple<std::set<std::variant<string::Epsilon, alphabet::Symbol>>, std::set<std::variant<string::Epsilon, alphabet::Symbol>>, std::set<std::variant<string::Epsilon, alphabet::Symbol>>> getLocalCallRetPartitioning(const automaton::RealTimeHeightDeterministicNPDA& n, const automaton::State& state) {
+	std::set<std::variant<string::Epsilon, alphabet::Symbol>> local;
+	std::set<std::variant<string::Epsilon, alphabet::Symbol>> call;
+	std::set<std::variant<string::Epsilon, alphabet::Symbol>> ret;
+
+	const std::set<label::Label> dSubSet = retrieveDSubSet(unpackFromStateLabel(state.getName()));
+
+	for(const auto& transition : n.getLocalTransitions()) {
+		if(dSubSet.count(transition.first.first.getName()))
+			local.insert(transition.first.second);
+	}
+
+	for(const auto& transition : n.getCallTransitions()) {
+		if(dSubSet.count(transition.first.first.getName()))
+			call.insert(transition.first.second);
+	}
+
+	for(const auto& transition : n.getReturnTransitions()) {
+		if(dSubSet.count(std::get<0>(transition.first).getName()))
+			ret.insert(std::get<1>(transition.first));
+	}
+
+	if(!std::empty_intersection(local, call))
+		throw exception::AlibException("Automaton is not real time height deterministic pushdown");
+
+	if(!std::empty_intersection(local, ret))
+		throw exception::AlibException("Automaton is not real time height deterministic pushdown");
+
+	if(!std::empty_intersection(call, ret))
+		throw exception::AlibException("Automaton is not real time height deterministic pushdown");
+
+	return std::make_tuple(local, call, ret);
+}
+
+automaton::RealTimeHeightDeterministicNPDA HDPDADeterminizer::determinize(const automaton::RealTimeHeightDeterministicNPDA& n) {
+	automaton::RealTimeHeightDeterministicNPDA d(n.getBottomOfTheStackSymbol());
+	d.setInputSymbols(n.getInputAlphabet());
+
+	label::Label initialLabel = packToStateLabel(createIdentity(retrieveLabels(n.getInitialStates())));
+	d.addState(automaton::State(initialLabel));
+	d.addInitialState(automaton::State(initialLabel));
+
+	for(;;) {
+		std::pair<automaton::State, alphabet::Symbol>* stateSymbol = existsDirtyStateSymbol(d, n);
+		const automaton::State* state = existsDirtyState(d, n);
+
+		if(stateSymbol == NULL && state == NULL) break;
+
+		if(stateSymbol != NULL) {
+			std::tuple<std::set<std::variant<string::Epsilon, alphabet::Symbol>>, std::set<std::variant<string::Epsilon, alphabet::Symbol>>, std::set<std::variant<string::Epsilon, alphabet::Symbol>>> partitioning = getLocalCallRetPartitioning(n, stateSymbol->first);
+
+			std::set<std::variant<string::Epsilon, alphabet::Symbol>>& retPart = std::get<2>(partitioning);
+
+			for(const auto& symbol : retPart) {
+				if(stateSymbol->second == d.getBottomOfTheStackSymbol()) {
+					retInitial(stateSymbol->first, stateSymbol->second, symbol, n, d);
+				} else {
+					ret(stateSymbol->first, stateSymbol->second, symbol, n, d);
+				}
+			}
+			delete stateSymbol; //TODO remove this...
+		}
+
+		if(state != NULL) {
+			std::tuple<std::set<std::variant<string::Epsilon, alphabet::Symbol>>, std::set<std::variant<string::Epsilon, alphabet::Symbol>>, std::set<std::variant<string::Epsilon, alphabet::Symbol>>> partitioning = getLocalCallRetPartitioning(n, *state);
+
+			std::set<std::variant<string::Epsilon, alphabet::Symbol>>& localPart = std::get<0>(partitioning);
+			std::set<std::variant<string::Epsilon, alphabet::Symbol>>& callPart = std::get<1>(partitioning);
+
+			for(const auto& symbol : localPart) {
+				local(*state, symbol, n, d);
+			}
+			for(const auto& symbol : callPart) {
+				call(*state, symbol, n, d);
+			}
+		}
+	}
+
+	std::set<label::Label> finalLabels = retrieveLabels(n.getFinalStates());
+	for(const automaton::State& state : d.getStates()) {
+		const std::set<label::Label> labels = retrieveDSubSet(unpackFromStateLabel(state.getName()));
+
+		if(!std::empty_intersection(finalLabels, labels)) {
+			d.addFinalState(state);
+		}
+	}
+	
+	return d;
+}
+
+}
diff --git a/alib2algo/src/determinize/hdpda/HDPDADeterminizer.h b/alib2algo/src/determinize/hdpda/HDPDADeterminizer.h
new file mode 100644
index 0000000000..97caaf125f
--- /dev/null
+++ b/alib2algo/src/determinize/hdpda/HDPDADeterminizer.h
@@ -0,0 +1,24 @@
+#ifndef HDPDA_DETERMINIZER_H_
+#define HDPDA_DETERMINIZER_H_
+
+#include "automaton/PDA/RealTimeHeightDeterministicNPDA.h"
+
+namespace determinize {
+
+/**
+ * Class for running basic determinization algorithm on vpa.
+ */
+class HDPDADeterminizer {
+public:
+	/**
+	 * Runs determinization algorithm on nondeterministic vpa given in constructor.
+	 *
+	 * @return deterministic visibly pushdown automaton
+	 */
+	static automaton::RealTimeHeightDeterministicNPDA determinize(const automaton::RealTimeHeightDeterministicNPDA& nondeterministic);
+
+};
+
+} /* namespace determinize */
+
+#endif /* HDPDA_DETERMINIZER_h_ */
diff --git a/alib2algo/src/determinize/vpa/VPADeterminizer.cpp b/alib2algo/src/determinize/vpa/VPADeterminizer.cpp
index 52a196b808..d36257bc41 100644
--- a/alib2algo/src/determinize/vpa/VPADeterminizer.cpp
+++ b/alib2algo/src/determinize/vpa/VPADeterminizer.cpp
@@ -1,51 +1,15 @@
 #include "VPADeterminizer.h"
+#include "../common/RHDPDACommon.h"
 
 #include "automaton/common/State.h"
 #include "alphabet/Symbol.h"
 #include "alphabet/LabeledSymbol.h"
 #include "label/Label.h"
-#include "label/LabelSetLabel.h"
-#include "label/LabelPairLabel.h"
-#include "label/ObjectLabel.h"
-#include "object/Object.h"
 #include <std/set.hpp>
 #include <iostream>
 
 namespace determinize {
 
-label::Label VPADeterminizer::packToDVPAStateLabel(std::set<std::pair<label::Label, label::Label>>&& data) {
-	std::set<label::Label> res;
-	for(auto&& subData : std::move(data)) {
-		res.insert(label::Label(label::LabelPairLabel(std::move(subData))));
-	}
-	return label::Label(label::LabelSetLabel(std::move(res)));
-}
-
-std::set<std::pair<label::Label, label::Label>> VPADeterminizer::unpackFromDVPAStateLabel(const label::Label& data) {
-	std::set<std::pair<label::Label, label::Label>> res;
-	const std::set<label::Label>& labelSet = static_cast<const label::LabelSetLabel&>(data.getData()).getData();
-	for (const auto& subData : labelSet) {
-		const std::pair<label::Label, label::Label>& labelPair = static_cast<const label::LabelPairLabel&>(subData.getData()).getData();
-		res.insert(labelPair);
-	}
-	return res;
-}
-
-label::Label VPADeterminizer::packToDVPAStackSymbolLabel(std::pair<std::set<std::pair<label::Label, label::Label>>, alphabet::Symbol>&& data) {
-	label::Label res1 = packToDVPAStateLabel(std::move(data.first));
-	label::Label res2 = label::Label(label::ObjectLabel(alib::Object(std::move(data.second.getData()))));
-	return label::Label(label::LabelPairLabel(std::make_pair(std::move(res1), std::move(res2))));
-}
-
-std::pair<std::set<std::pair<label::Label, label::Label>>, alphabet::Symbol> VPADeterminizer::unpackFromDVPAStackSymbolLabel(const label::Label& data) {
-	const label::Label& labelPairFirst = static_cast<const label::LabelPairLabel&>(data.getData()).getData().first;
-	std::set<std::pair<label::Label, label::Label>> res = unpackFromDVPAStateLabel(labelPairFirst);
-
-	const label::Label& labelPairSecond = static_cast<const label::LabelPairLabel&>(data.getData()).getData().second;
-	const alib::Object& object = static_cast<const label::ObjectLabel&>(labelPairSecond.getData()).getData();
-	return std::make_pair(std::move(res), alphabet::Symbol(static_cast<const alphabet::SymbolBase&>(object.getData())));
-}
-
 void addRetTransition(const automaton::State& from, const alphabet::Symbol& input, const alphabet::Symbol& dvpdaSymbol, const automaton::State& to, automaton::VisiblyPushdownNPDA& deterministic) {
 	deterministic.addState(from);
 	deterministic.addState(to);
@@ -55,7 +19,7 @@ void addRetTransition(const automaton::State& from, const alphabet::Symbol& inpu
 }
 
 void retInitial(const automaton::State& state, const alphabet::Symbol& pdaSymbol, const alphabet::Symbol& input, const automaton::VisiblyPushdownNPDA& nondeterministic, automaton::VisiblyPushdownNPDA& deterministic) {
-	std::set<std::pair<label::Label, label::Label>> S = VPADeterminizer::unpackFromDVPAStateLabel(state.getName());
+	std::set<std::pair<label::Label, label::Label>> S = unpackFromStateLabel(state.getName());
 
 	std::set<std::pair<label::Label, label::Label>> S1;
 	for(const auto& entry : S) {
@@ -74,12 +38,12 @@ void retInitial(const automaton::State& state, const alphabet::Symbol& pdaSymbol
 		}
 	}
 
-	addRetTransition(state, input, pdaSymbol, automaton::State(VPADeterminizer::packToDVPAStateLabel(std::move(S1))), deterministic);
+	addRetTransition(state, input, pdaSymbol, automaton::State(packToStateLabel(std::move(S1))), deterministic);
 }
 
 void ret(const automaton::State& state, const alphabet::Symbol& pdaSymbol, const alphabet::Symbol& input, const automaton::VisiblyPushdownNPDA& nondeterministic, automaton::VisiblyPushdownNPDA& deterministic) {
-	std::set<std::pair<label::Label, label::Label>> S = VPADeterminizer::unpackFromDVPAStateLabel(state.getName());
-	std::pair<std::set<std::pair<label::Label, label::Label>>, alphabet::Symbol> pdaSymbolUnpack = VPADeterminizer::unpackFromDVPAStackSymbolLabel(static_cast<const alphabet::LabeledSymbol&>(pdaSymbol.getData()).getLabel());
+	std::set<std::pair<label::Label, label::Label>> S = unpackFromStateLabel(state.getName());
+	std::pair<std::set<std::pair<label::Label, label::Label>>, alphabet::Symbol> pdaSymbolUnpack = unpackFromDVPAStackSymbolLabel(static_cast<const alphabet::LabeledSymbol&>(pdaSymbol.getData()).getLabel());
 	const std::set<std::pair<label::Label, label::Label>>& S1 = pdaSymbolUnpack.first;
 
 	std::set<std::pair<label::Label, label::Label>> update;
@@ -124,7 +88,7 @@ void ret(const automaton::State& state, const alphabet::Symbol& pdaSymbol, const
 		}
 	}
 
-	addRetTransition(state, input, pdaSymbol, automaton::State(VPADeterminizer::packToDVPAStateLabel(std::move(S2))), deterministic);
+	addRetTransition(state, input, pdaSymbol, automaton::State(packToStateLabel(std::move(S2))), deterministic);
 }
 
 void addCallTransition(const automaton::State& from, const alphabet::Symbol& input, const automaton::State& to, const alphabet::Symbol& dvpdaSymbol, automaton::VisiblyPushdownNPDA& deterministic) {
@@ -135,24 +99,8 @@ void addCallTransition(const automaton::State& from, const alphabet::Symbol& inp
 	deterministic.addCallTransition(from, input, to, dvpdaSymbol);
 }
 
-std::set<label::Label> retrieveDSubSet(const std::set<std::pair<label::Label, label::Label>>& localOperation) {
-	std::set<label::Label> id;
-	for(const auto& entry : localOperation) {
-		id.insert(entry.second);
-	}
-	return id;
-}
-
-std::set<std::pair<label::Label, label::Label>> createIdentity(std::set<label::Label>&& states) {
-	std::set<std::pair<label::Label, label::Label>> id;
-	for(const label::Label& state : states) {
-		id.insert(std::make_pair(state, state));
-	}
-	return id;
-}
-
 void call(const automaton::State& state, const alphabet::Symbol& input, const automaton::VisiblyPushdownNPDA& nondeterministic, automaton::VisiblyPushdownNPDA& deterministic) {
-	std::set<std::pair<label::Label, label::Label>> S = VPADeterminizer::unpackFromDVPAStateLabel(state.getName());
+	std::set<std::pair<label::Label, label::Label>> S = unpackFromStateLabel(state.getName());
 
 	std::set<label::Label> R = retrieveDSubSet(S);
 	std::set<label::Label> R1;
@@ -170,7 +118,7 @@ void call(const automaton::State& state, const alphabet::Symbol& input, const au
 		}
 	}
 
-	addCallTransition(state, input, automaton::State(VPADeterminizer::packToDVPAStateLabel(createIdentity(std::move(R1)))), alphabet::Symbol(alphabet::LabeledSymbol(VPADeterminizer::packToDVPAStackSymbolLabel(std::make_pair(std::move(S), input)))), deterministic);
+	addCallTransition(state, input, automaton::State(packToStateLabel(createIdentity(std::move(R1)))), alphabet::Symbol(alphabet::LabeledSymbol(packToStackSymbolLabel(std::make_pair(std::move(S), input)))), deterministic);
 }
 
 void addLocalTransition(const automaton::State& from, const alphabet::Symbol& input, const automaton::State& to, automaton::VisiblyPushdownNPDA& deterministic) {
@@ -181,7 +129,7 @@ void addLocalTransition(const automaton::State& from, const alphabet::Symbol& in
 }
 
 void local(const automaton::State& state, const alphabet::Symbol& input, const automaton::VisiblyPushdownNPDA& nondeterministic, automaton::VisiblyPushdownNPDA& deterministic) {
-	std::set<std::pair<label::Label, label::Label>> S = VPADeterminizer::unpackFromDVPAStateLabel(state.getName());
+	std::set<std::pair<label::Label, label::Label>> S = unpackFromStateLabel(state.getName());
 	std::set<std::pair<label::Label, label::Label>> S1;
 
 	for(const auto& entry : S) {
@@ -199,96 +147,7 @@ void local(const automaton::State& state, const alphabet::Symbol& input, const a
 		}
 	}
 	
-	addLocalTransition(state, input, automaton::State(VPADeterminizer::packToDVPAStateLabel(std::move(S1))), deterministic);
-}
-
-const automaton::State* existsDirtyState(const automaton::VisiblyPushdownNPDA& d) {
-	for(const automaton::State& state : d.getStates()) {
-		const label::Label& stateLabel = state.getName();
-		
-		for(const auto& transition : d.getCallTransitions()) {
-			if(stateLabel != transition.first.first.getName()) continue;
-
-			goto continue2;
-		}
-		return &state;
-
-continue2: while(false); //TODO remove this
-	}
-	return NULL;
-}
-
-void localClosure(std::set<label::Label>& states, const std::set<label::Label>& oldStates, const automaton::VisiblyPushdownNPDA& d) {
-	std::set<label::Label> newStates;
-
-	for(const label::Label& state : oldStates) {
-		for(const auto& transition : d.getLocalTransitions()) {
-			if(transition.second.begin()->getName() != state) continue;
-
-			if(!states.count(transition.first.first.getName())) {
-				states.insert(transition.first.first.getName());
-				newStates.insert(transition.first.first.getName());
-			}
-		}
-
-		for(const auto& transition : d.getReturnTransitions()) {
-			if(transition.second.begin()->getName() != state) continue;
-
-			const alphabet::Symbol& popSymbol = std::get<2>(transition.first);
-			if(popSymbol == d.getBottomOfTheStackSymbol()) continue;
-			const label::Label& popSymbolLabel = static_cast<const alphabet::LabeledSymbol&>(popSymbol.getData()).getLabel();
-			const label::Label& statePart = static_cast<const label::LabelPairLabel&>(popSymbolLabel.getData()).getData().first;
-
-			if(!states.count(statePart)) {
-				states.insert(statePart);
-				newStates.insert(statePart);
-			}
-		}
-	}
-
-	if(newStates.empty()) return;
-	localClosure(states, newStates, d);
-}
-
-std::pair<automaton::State, alphabet::Symbol>* existsDirtyStateSymbol(const automaton::VisiblyPushdownNPDA& d) {
-	for(const automaton::State& state : d.getStates()) {
-		const label::Label& stateLabel = state.getName();
-
-		std::set<label::Label> lc { stateLabel };
-		localClosure(lc, std::set<label::Label>{stateLabel}, d); //intentional copy
-
-		std::set<alphabet::Symbol> topSymbols;
-		for(const label::Label& localState : lc) {
-			for(const auto& transition : d.getCallTransitions()) {
-				for(const auto& to : transition.second) {
-					if(localState != to.first.getName()) continue;
-
-					topSymbols.insert(to.second);
-				}
-			}
-
-			if(d.getInitialStates().begin()->getName() == localState) {
-				topSymbols.insert(d.getBottomOfTheStackSymbol());
-			}
-		}
-
-		for(const auto& transition : d.getReturnTransitions()) {
-			if(stateLabel != std::get<0>(transition.first).getName()) continue;
-
-			topSymbols.erase(std::get<2>(transition.first));
-		}
-
-		if(!topSymbols.empty()) return new std::pair<automaton::State, alphabet::Symbol>(automaton::State(stateLabel), *topSymbols.begin());
-	}
-	return NULL;
-}
-
-std::set<label::Label> retrieveLabels(const std::set<automaton::State>& states) {
-	std::set<label::Label> labels;
-	for(const automaton::State& state : states) {
-		labels.insert(state.getName());
-	}
-	return labels;
+	addLocalTransition(state, input, automaton::State(packToStateLabel(std::move(S1))), deterministic);
 }
 
 automaton::VisiblyPushdownNPDA VPADeterminizer::determinize(const automaton::VisiblyPushdownNPDA& n) {
@@ -297,13 +156,13 @@ automaton::VisiblyPushdownNPDA VPADeterminizer::determinize(const automaton::Vis
 	d.setLocalInputSymbols(n.getLocalInputAlphabet());
 	d.setReturnInputSymbols(n.getReturnInputAlphabet());
 	
-	label::Label initialLabel = VPADeterminizer::packToDVPAStateLabel(createIdentity(retrieveLabels(n.getInitialStates())));
+	label::Label initialLabel = packToStateLabel(createIdentity(retrieveLabels(n.getInitialStates())));
 	d.addState(automaton::State(initialLabel));
 	d.addInitialState(automaton::State(initialLabel));
 	
 	for(;;) {
-		std::pair<automaton::State, alphabet::Symbol>* stateSymbol = existsDirtyStateSymbol(d);
-		const automaton::State* state = existsDirtyState(d);
+		std::pair<automaton::State, alphabet::Symbol>* stateSymbol = existsDirtyStateSymbol(d, n);
+		const automaton::State* state = existsDirtyState(d, n);
 		if(stateSymbol != NULL) {
 			for(const alphabet::Symbol& symbol : n.getReturnInputAlphabet()) {
 				if(stateSymbol->second == d.getBottomOfTheStackSymbol()) {
@@ -317,7 +176,7 @@ automaton::VisiblyPushdownNPDA VPADeterminizer::determinize(const automaton::Vis
 			for(const alphabet::Symbol& symbol : n.getLocalInputAlphabet()) {
 				local(*state, symbol, n, d);
 			}
-			for(const alphabet::Symbol symbol : n.getCallInputAlphabet()) {
+			for(const alphabet::Symbol& symbol : n.getCallInputAlphabet()) {
 				call(*state, symbol, n, d);
 			}
 		} else {
@@ -327,7 +186,7 @@ automaton::VisiblyPushdownNPDA VPADeterminizer::determinize(const automaton::Vis
 
 	std::set<label::Label> finalLabels = retrieveLabels(n.getFinalStates());
 	for(const automaton::State& state : d.getStates()) {
-		const std::set<label::Label> labels = retrieveDSubSet(VPADeterminizer::unpackFromDVPAStateLabel(state.getName()));
+		const std::set<label::Label> labels = retrieveDSubSet(unpackFromStateLabel(state.getName()));
 
 		if(!std::empty_intersection(finalLabels, labels)) {
 			d.addFinalState(state);
diff --git a/alib2algo/src/determinize/vpa/VPADeterminizer.h b/alib2algo/src/determinize/vpa/VPADeterminizer.h
index 0910496ee8..d305786129 100644
--- a/alib2algo/src/determinize/vpa/VPADeterminizer.h
+++ b/alib2algo/src/determinize/vpa/VPADeterminizer.h
@@ -10,13 +10,6 @@ namespace determinize {
  */
 class VPADeterminizer {
 public:
-	static label::Label packToDVPAStateLabel(std::set<std::pair<label::Label, label::Label>>&& data);
-
-	static std::set<std::pair<label::Label, label::Label>> unpackFromDVPAStateLabel(const label::Label& data);
-
-	static label::Label packToDVPAStackSymbolLabel(std::pair<std::set<std::pair<label::Label, label::Label>>, alphabet::Symbol>&& data);
-
-	static std::pair<std::set<std::pair<label::Label, label::Label>>, alphabet::Symbol> unpackFromDVPAStackSymbolLabel(const label::Label& data);
 	/**
 	 * Runs determinization algorithm on nondeterministic vpa given in constructor.
 	 *
-- 
GitLab