From 0459d0beee2d1cfd624e4c1759e23758594d564e Mon Sep 17 00:00:00 2001
From: Jakub Doupal <doupajak@fit.cvut.cz>
Date: Sat, 14 May 2016 19:18:54 +0200
Subject: [PATCH] Added run capabilities for NPDTA

---
 alib2algo/src/automaton/run/Accept.cpp    |   9 ++
 alib2algo/src/automaton/run/Accept.h      |   1 +
 alib2algo/src/automaton/run/Run.cpp       | 100 ++++++++++++++++++++++
 alib2algo/src/automaton/run/Run.h         |   1 +
 alib2algo/src/automaton/run/Translate.cpp |  41 +++++++++
 alib2algo/src/automaton/run/Translate.h   |  38 ++++++++
 arun2/src/arun.cpp                        |   9 ++
 7 files changed, 199 insertions(+)
 create mode 100644 alib2algo/src/automaton/run/Translate.cpp
 create mode 100644 alib2algo/src/automaton/run/Translate.h

diff --git a/alib2algo/src/automaton/run/Accept.cpp b/alib2algo/src/automaton/run/Accept.cpp
index 47089a7f5c..89ee3e4888 100644
--- a/alib2algo/src/automaton/run/Accept.cpp
+++ b/alib2algo/src/automaton/run/Accept.cpp
@@ -15,8 +15,10 @@
 #include <automaton/PDA/VisiblyPushdownDPDA.h>
 #include <automaton/PDA/RealTimeHeightDeterministicDPDA.h>
 #include <automaton/PDA/DPDA.h>
+#include <automaton/PDA/NPDTA.h>
 
 #include <deque>
+#include <vector>
 #include <algorithm>
 
 namespace automaton {
@@ -103,6 +105,13 @@ bool Accept::accept ( const automaton::DPDA & automaton, const string::LinearStr
 
 auto AcceptDPDALinearString = Accept::RegistratorWrapper < bool, automaton::DPDA, string::LinearString > ( Accept::accept );
 
+bool Accept::accept ( const automaton::NPDTA & automaton, const string::LinearString & string ) {
+	std::tuple < bool, std::set < automaton::State >, std::set < std::vector < alphabet::Symbol > > > res = Run::calculateStates ( automaton, string );
+	return std::get<0>(res);
+}
+
+auto AcceptNPDTALinearString = Accept::RegistratorWrapper < bool, automaton::NPDTA, string::LinearString > ( Accept::accept );
+
 } /* namespace run */
 
 } /* namespace automaton */
diff --git a/alib2algo/src/automaton/run/Accept.h b/alib2algo/src/automaton/run/Accept.h
index 4497396694..fa2d0fd08a 100644
--- a/alib2algo/src/automaton/run/Accept.h
+++ b/alib2algo/src/automaton/run/Accept.h
@@ -36,6 +36,7 @@ public:
 	static bool accept ( const automaton::VisiblyPushdownDPDA & automaton, const string::LinearString & string );
 	static bool accept ( const automaton::RealTimeHeightDeterministicDPDA & automaton, const string::LinearString & string );
 	static bool accept ( const automaton::DPDA & automaton, const string::LinearString & string );
+	static bool accept ( const automaton::NPDTA & automaton, const string::LinearString & string );
 
 };
 
diff --git a/alib2algo/src/automaton/run/Run.cpp b/alib2algo/src/automaton/run/Run.cpp
index 2e17ab5f8b..3580d1bc9f 100644
--- a/alib2algo/src/automaton/run/Run.cpp
+++ b/alib2algo/src/automaton/run/Run.cpp
@@ -14,9 +14,11 @@
 #include <automaton/PDA/VisiblyPushdownDPDA.h>
 #include <automaton/PDA/RealTimeHeightDeterministicDPDA.h>
 #include <automaton/PDA/DPDA.h>
+#include <automaton/PDA/NPDTA.h>
 #include <global/GlobalData.h>
 
 #include <deque>
+#include <algorithm>
 
 namespace automaton {
 
@@ -468,6 +470,104 @@ std::tuple < bool, State, std::set < unsigned >, std::deque < alphabet::Symbol >
 
 // ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
+struct graphStructuredStack {
+	graphStructuredStack ( graphStructuredStack * parent, alphabet::Symbol data ) : parent(parent), data(data) {}
+	graphStructuredStack * parent;
+	alphabet::Symbol data;
+};
+
+std::tuple < bool, std::set < State >, std::set < std::vector < alphabet::Symbol > > > Run::calculateStates ( const automaton::NPDTA & automaton, const string::LinearString & string ) {
+	bool res = false;
+	unsigned i = 0;
+	std::set < unsigned > occurrences;
+	automaton::State state = automaton . getInitialState ();
+	std::vector<alphabet::Symbol>::const_iterator symbolIter = string . getContent () . begin ();
+	graphStructuredStack * stackNode = new graphStructuredStack ( NULL, (* symbolIter) );
+	graphStructuredStack * outputNode = new graphStructuredStack ( NULL, (* symbolIter) );
+	std::set < graphStructuredStack* > allNodes { stackNode, outputNode };
+
+	if ( automaton . getFinalStates () . count ( state ) ) {
+		occurrences . insert ( i );
+	}
+
+	std::deque < std::tuple < automaton::State, std::vector<alphabet::Symbol>::const_iterator, graphStructuredStack*, graphStructuredStack* > > bftQueue;
+	auto configuration = std::make_tuple ( state, symbolIter, stackNode, outputNode );
+	bftQueue . push_back ( configuration );
+
+	std::set < std::vector < alphabet::Symbol > > allOutputs;
+	std::set < State > states;
+
+	while ( ! bftQueue . empty () ) {
+		configuration = bftQueue . front (); bftQueue . pop_front ();
+		state = std::get<0>(configuration);
+		symbolIter = std::get<1>(configuration);
+		stackNode = std::get<2>(configuration);
+		outputNode = std::get<3>(configuration);
+
+		if ( symbolIter == string . getContent () . end () ) {
+			states . insert ( state );
+			if ( automaton . getFinalStates () . count ( state ) && stackNode -> parent == NULL ) {
+				res = true;
+				std::vector < alphabet::Symbol > output;
+				while ( outputNode->parent != NULL ) {
+					output . push_back ( outputNode->data );
+					outputNode = outputNode -> parent;
+				}
+				std::reverse ( output.begin(), output.end() );
+				allOutputs . insert ( output );
+			}
+			continue;
+		}
+
+		auto transitions = automaton . getTransitionsFromState ( state );
+		for ( auto transition = transitions . begin (); transition != transitions . end (); transition ++ ) {
+			if ( std::get<1>(transition -> first) != (* symbolIter) && ! std::get<1>(transition -> first) . is<string::Epsilon>() ) {
+				continue;
+			}
+			auto pop = std::get<2>(transition -> first);
+			graphStructuredStack * stackNodeCopy = stackNode;
+			graphStructuredStack * outputNodeCopy = outputNode;
+
+			unsigned j = 0;
+			for ( ; j < pop . size (); j ++ ) {
+				if ( stackNodeCopy->parent == NULL || stackNodeCopy->data != pop . at (j) ) {
+					break;
+				}
+				stackNodeCopy = stackNodeCopy -> parent;
+			}			
+			if ( j == pop . size () ) {
+				for ( auto iter = (std::get<1>(transition -> second)).rbegin(); iter != (std::get<1>(transition -> second)).rend(); iter ++ ) {
+					stackNodeCopy = new graphStructuredStack ( stackNodeCopy, (* iter) );
+					allNodes . insert ( stackNodeCopy );
+				}
+				for ( auto iter = (std::get<2>(transition -> second)).begin(); iter != (std::get<2>(transition -> second)).end(); iter ++ ) {
+					outputNodeCopy = new graphStructuredStack ( outputNodeCopy, (* iter) );
+					allNodes . insert ( outputNodeCopy );
+				}
+
+				if ( ! std::get<1>(transition -> first) . is<string::Epsilon>() ) {
+					configuration = std::make_tuple ( std::get<0>(transition -> second), symbolIter + 1, stackNodeCopy, outputNodeCopy );
+				}
+				else {
+					configuration = std::make_tuple ( std::get<0>(transition -> second), symbolIter, stackNodeCopy, outputNodeCopy );					
+				}
+				bftQueue . push_back ( configuration );
+			}
+			else {
+				states . insert ( state );
+			}
+		}
+	}
+
+	for ( auto iter = allNodes . begin (); iter != allNodes . end (); iter ++ ) {
+		delete (* iter);
+	}
+
+	return std::make_tuple ( res, states, allOutputs );
+}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
 } /* namespace run */
 
 } /* namespace automaton */
diff --git a/alib2algo/src/automaton/run/Run.h b/alib2algo/src/automaton/run/Run.h
index 1f71d44ce8..477f486dbf 100644
--- a/alib2algo/src/automaton/run/Run.h
+++ b/alib2algo/src/automaton/run/Run.h
@@ -32,6 +32,7 @@ public:
 	static std::tuple < bool, State, std::set < unsigned >, std::deque < alphabet::Symbol > > calculateState ( const automaton::VisiblyPushdownDPDA & automaton, const string::LinearString & string );
 	static std::tuple < bool, State, std::set < unsigned >, std::deque < alphabet::Symbol > > calculateState ( const automaton::RealTimeHeightDeterministicDPDA & automaton, const string::LinearString & string );
 	static std::tuple < bool, State, std::set < unsigned >, std::deque < alphabet::Symbol > > calculateState ( const automaton::DPDA & automaton, const string::LinearString & string );
+	static std::tuple < bool, std::set < State >, std::set < std::vector < alphabet::Symbol > > > calculateStates ( const automaton::NPDTA & automaton, const string::LinearString & string );
 };
 
 } /* namespace run */
diff --git a/alib2algo/src/automaton/run/Translate.cpp b/alib2algo/src/automaton/run/Translate.cpp
new file mode 100644
index 0000000000..4b430d1681
--- /dev/null
+++ b/alib2algo/src/automaton/run/Translate.cpp
@@ -0,0 +1,41 @@
+/*
+ * Translate.cpp
+ *
+ *  Created on: 12. 5. 2016
+ *      Author: Jakub Doupal
+ */
+
+#include "Translate.h"
+#include "Run.h"
+#include <automaton/PDA/NPDTA.h>
+
+#include <deque>
+#include <set>
+
+namespace automaton {
+
+namespace run {
+
+std::set < string::LinearString > Translate::translate ( const automaton::Automaton & automaton, const alib::Object & object ) {
+	return dispatch ( automaton.getData ( ), object.getData ( ) );
+}
+
+std::set < string::LinearString > Translate::translate ( const automaton::Automaton & automaton, const string::LinearString & string ) {
+	return dispatch ( automaton.getData ( ), string );
+}
+
+std::set < string::LinearString > Translate::translate ( const automaton::NPDTA & automaton, const string::LinearString & string ) {
+	std::tuple < bool, std::set < automaton::State >, std::set < std::vector < alphabet::Symbol > > > res = Run::calculateStates ( automaton, string );
+	std::set < string::LinearString > strings;
+	for ( auto iter = std::get<2>(res).begin(); iter != std::get<2>(res).end(); iter ++ ) {
+		string::LinearString str (* iter);
+		strings . insert ( str );
+	}
+	return strings;
+}
+
+auto TranslateNPDTALinearString = Translate::RegistratorWrapper < std::set < string::LinearString >, automaton::NPDTA, string::LinearString > ( Translate::translate );
+
+} /* namespace run */
+
+} /* namespace automaton */
diff --git a/alib2algo/src/automaton/run/Translate.h b/alib2algo/src/automaton/run/Translate.h
new file mode 100644
index 0000000000..2b52617679
--- /dev/null
+++ b/alib2algo/src/automaton/run/Translate.h
@@ -0,0 +1,38 @@
+/*
+ * Translate.h
+ *
+ *  Created on: 12. 5. 2016
+ *      Author: Jakub Doupal
+ */
+
+#ifndef _AUTOMATON_TRANSLATE_H__
+#define _AUTOMATON_TRANSLATE_H__
+
+#include <core/multipleDispatch.hpp>
+#include <automaton/Automaton.h>
+#include <object/Object.h>
+#include <string/LinearString.h>
+#include <alphabet/Symbol.h>
+
+namespace automaton {
+
+namespace run {
+
+class Translate : public std::DoubleDispatch < Translate, std::set < string::LinearString >, automaton::AutomatonBase, alib::ObjectBase > {
+public:
+	/**
+	 * Performs conversion.
+	 * @return left regular grammar equivalent to source automaton.
+	 */
+	static std::set < string::LinearString > translate ( const automaton::Automaton & automaton, const alib::Object & object );
+	static std::set < string::LinearString > translate ( const automaton::Automaton & automaton, const string::LinearString & string );
+
+	static std::set < string::LinearString > translate ( const automaton::NPDTA & automaton, const string::LinearString & string );
+
+};
+
+} /* namespace run */
+
+} /* namespace automaton */
+
+#endif /* _AUTOMATON_TRANSLATE_H__ */
diff --git a/arun2/src/arun.cpp b/arun2/src/arun.cpp
index 900f83169c..c871afe952 100644
--- a/arun2/src/arun.cpp
+++ b/arun2/src/arun.cpp
@@ -20,6 +20,7 @@
 #include <automaton/Automaton.h>
 #include <automaton/run/Accept.h>
 #include <automaton/run/Result.h>
+#include <automaton/run/Translate.h>
 #include <automaton/run/Occurrences.h>
 #include <container/ObjectsSet.h>
 
@@ -36,6 +37,7 @@ int main(int argc, char* argv[]) {
 		allowed.push_back("occurrences");
 		allowed.push_back("accept");
 		allowed.push_back("result");
+		allowed.push_back("translate");
 		TCLAP::ValuesConstraint<std::string> allowedVals( allowed );
 
 		TCLAP::ValueArg<std::string> type(	"t",	"type",		"Run type",		false,	"accept",	&allowedVals);
@@ -89,6 +91,13 @@ int main(int argc, char* argv[]) {
 			measurements::end();
 			measurements::start("Output write", measurements::Type::AUXILIARY);
 
+			alib::XmlDataFactory::toStdout( res );
+		} else if( type.getValue() == "translate") {
+			std::set < string::LinearString > res = automaton::run::Translate::translate(automatonData, inputData);
+
+			measurements::end();
+			measurements::start("Output write", measurements::Type::AUXILIARY);
+
 			alib::XmlDataFactory::toStdout( res );
 		} else {
 			throw exception::CommonException( "Invalid run type" );
-- 
GitLab