From 3df74417811af0dacace5398deb8ea16e48eb0d1 Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Sun, 28 Jan 2018 18:28:37 +0100
Subject: [PATCH] nonlinear TreePatternAutomaton for ranked bar tree

---
 .../ExactNonlinearTreePatternAutomaton.cpp    |   2 +
 .../ExactNonlinearTreePatternAutomaton.h      | 165 ++++++++++++++++--
 2 files changed, 152 insertions(+), 15 deletions(-)

diff --git a/alib2algo/src/arbology/exact/ExactNonlinearTreePatternAutomaton.cpp b/alib2algo/src/arbology/exact/ExactNonlinearTreePatternAutomaton.cpp
index 039bf423ae..9729933507 100644
--- a/alib2algo/src/arbology/exact/ExactNonlinearTreePatternAutomaton.cpp
+++ b/alib2algo/src/arbology/exact/ExactNonlinearTreePatternAutomaton.cpp
@@ -14,6 +14,8 @@ namespace exact {
 
 auto ExactNonlinearTreePatternAutomatonPrefixRankedTree = registration::AbstractRegister < ExactNonlinearTreePatternAutomaton, automaton::InputDrivenNPDA < common::ranked_symbol < DefaultSymbolType, DefaultRankType >, char, ext::pair < unsigned, unsigned > >, const tree::PrefixRankedTree < > &, const common::ranked_symbol < DefaultSymbolType, DefaultRankType > &, const ext::set < common::ranked_symbol < DefaultSymbolType, DefaultRankType > > & > ( ExactNonlinearTreePatternAutomaton::construct );
 
+auto ExactNonlinearTreePatternAutomatonPrefixRankedBarTree = registration::AbstractRegister < ExactNonlinearTreePatternAutomaton, automaton::InputDrivenNPDA < common::ranked_symbol < DefaultSymbolType, DefaultRankType >, char, ext::pair < unsigned, unsigned > >, const tree::PrefixRankedBarTree < > &, const common::ranked_symbol < DefaultSymbolType, DefaultRankType > &, const ext::set < common::ranked_symbol < DefaultSymbolType, DefaultRankType > > &, const common::ranked_symbol < DefaultSymbolType, DefaultRankType > & > ( ExactNonlinearTreePatternAutomaton::construct );
+
 } /* namespace exact */
 
 } /* namespace arbology */
diff --git a/alib2algo/src/arbology/exact/ExactNonlinearTreePatternAutomaton.h b/alib2algo/src/arbology/exact/ExactNonlinearTreePatternAutomaton.h
index df349761e6..6fdb164606 100644
--- a/alib2algo/src/arbology/exact/ExactNonlinearTreePatternAutomaton.h
+++ b/alib2algo/src/arbology/exact/ExactNonlinearTreePatternAutomaton.h
@@ -28,7 +28,13 @@ class ExactNonlinearTreePatternAutomaton {
 	static automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > constructInternal ( const tree::PrefixRankedTree < SymbolType, RankType > & tree, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, const common::ranked_symbol < SymbolType, RankType > & currentNonlinearVariable, const ext::set < common::ranked_symbol < SymbolType, RankType > > & nonlinearVariables );
 
 	template < class SymbolType, class RankType >
-	static void constructTail ( automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > & res, const tree::PrefixRankedTree < SymbolType, RankType > & tree, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, const common::ranked_symbol < SymbolType, RankType > & currentNonlinearVariable, const ext::set < common::ranked_symbol < SymbolType, RankType > > & nonlinearVariables, unsigned subtreeId, typename ext::vector < common::ranked_symbol < SymbolType, RankType > >::const_iterator rankedSymbolsIter, int i, typename ext::vector < common::ranked_symbol < unsigned, RankType > >::const_iterator subtreeRepeatsIter );
+	static void constructTail ( automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > & res, const tree::PrefixRankedTree < SymbolType, RankType > & tree, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, const common::ranked_symbol < SymbolType, RankType > & currentNonlinearVariable, const ext::set < common::ranked_symbol < SymbolType, RankType > > & nonlinearVariables, unsigned subtreeId, typename ext::vector < common::ranked_symbol < SymbolType, RankType > >::const_iterator rankedSymbolsIter, unsigned i, typename ext::vector < common::ranked_symbol < unsigned, RankType > >::const_iterator subtreeRepeatsIter );
+
+	template < class SymbolType, class RankType >
+	static automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > constructInternal ( const tree::PrefixRankedBarTree < SymbolType, RankType > & tree, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, const common::ranked_symbol < SymbolType, RankType > & currentNonlinearVariable, const ext::set < common::ranked_symbol < SymbolType, RankType > > & nonlinearVariables, const common::ranked_symbol < SymbolType, RankType > & variablesBar );
+
+	template < class SymbolType, class RankType >
+	static void constructTail ( automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > & res, const tree::PrefixRankedBarTree < SymbolType, RankType > & tree, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, const common::ranked_symbol < SymbolType, RankType > & currentNonlinearVariable, const ext::set < common::ranked_symbol < SymbolType, RankType > > & nonlinearVariables, const common::ranked_symbol < SymbolType, RankType > & variablesBar, unsigned subtreeId, typename ext::vector < common::ranked_symbol < SymbolType, RankType > >::const_iterator rankedSymbolsIter, unsigned i, typename ext::vector < common::ranked_symbol < unsigned, RankType > >::const_iterator subtreeRepeatsIter );
 
 public:
 	/**
@@ -37,11 +43,18 @@ public:
 	 */
 	template < class SymbolType, class RankType >
 	static automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > construct ( const tree::PrefixRankedTree < SymbolType, RankType > & tree, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, const ext::set < common::ranked_symbol < SymbolType, RankType > > & nonlinearVariables );
+
+	/**
+	 * Performs conversion.
+	 * @return left regular grammar equivalent to source automaton.
+	 */
+	template < class SymbolType, class RankType >
+	static automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > construct ( const tree::PrefixRankedBarTree < SymbolType, RankType > & tree, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, const ext::set < common::ranked_symbol < SymbolType, RankType > > & nonlinearVariables, const common::ranked_symbol < SymbolType, RankType > & variablesBar );
 };
 
 template < class SymbolType, class RankType >
-void ExactNonlinearTreePatternAutomaton::constructTail ( automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > & res, const tree::PrefixRankedTree < SymbolType, RankType > & tree, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, const common::ranked_symbol < SymbolType, RankType > & currentNonlinearVariable, const ext::set < common::ranked_symbol < SymbolType, RankType > > & nonlinearVariables, unsigned subtreeId, typename ext::vector < common::ranked_symbol < SymbolType, RankType > >::const_iterator rankedSymbolsIter, int i, typename ext::vector < common::ranked_symbol < unsigned, RankType > >::const_iterator subtreeRepeatsIter ) {
-	ext::deque < std::pair < size_t, int > > subtreeJumps;
+void ExactNonlinearTreePatternAutomaton::constructTail ( automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > & res, const tree::PrefixRankedTree < SymbolType, RankType > & tree, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, const common::ranked_symbol < SymbolType, RankType > & currentNonlinearVariable, const ext::set < common::ranked_symbol < SymbolType, RankType > > & nonlinearVariables, unsigned subtreeId, typename ext::vector < common::ranked_symbol < SymbolType, RankType > >::const_iterator rankedSymbolsIter, unsigned i, typename ext::vector < common::ranked_symbol < unsigned, RankType > >::const_iterator subtreeRepeatsIter ) {
+	ext::deque < std::pair < size_t, unsigned > > subtreeJumps;
 	ext::deque < unsigned > subtreeRepeatsStack;
 
 	for (++ rankedSymbolsIter, ++ subtreeRepeatsIter, ++i; rankedSymbolsIter != tree.getContent ( ).end ( ); ++ rankedSymbolsIter, ++ subtreeRepeatsIter, ++i ) {
@@ -57,12 +70,12 @@ void ExactNonlinearTreePatternAutomaton::constructTail ( automaton::InputDrivenN
 		res.addTransition ( previousState, std::move ( symbol ), currentState );
 
 		while ( subtreeJumps.size ( ) && subtreeJumps.back ( ).first == 0 ) {
-			ext::pair < unsigned, unsigned > jumpSource = ext::make_pair ( subtreeJumps.back ( ).second, subtreeId + 1 );
-			res.addTransition ( jumpSource, subtreeWildcard, currentState );
+			ext::pair < unsigned, unsigned > source = ext::make_pair ( subtreeJumps.back ( ).second, subtreeId + 1 );
+			res.addTransition ( source, subtreeWildcard, currentState );
 
 			for ( const common::ranked_symbol < SymbolType, RankType > & nonlinearVariable : nonlinearVariables )
 				if ( nonlinearVariable != currentNonlinearVariable || subtreeId == subtreeRepeatsStack.back ( ) )
-					res.addTransition ( jumpSource, nonlinearVariable, currentState );
+					res.addTransition ( source, nonlinearVariable, currentState );
 
 			if ( subtreeJumps.size ( ) ) {
 				subtreeJumps.pop_back ( );
@@ -79,9 +92,9 @@ automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, cha
 	char S = alphabet::SubtreeWildcardSymbol::instance < char > ( );
 	automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > res ( ext::make_pair ( 0u, 0u ), S );
 
-	tree::PrefixRankedTree < unsigned, DefaultRankType > repeats = tree::properties::ExactSubtreeRepeatsNaive::repeats ( tree );
+	tree::PrefixRankedTree < unsigned, RankType > repeats = tree::properties::ExactSubtreeRepeatsNaive::repeats ( tree );
 
-	for ( const common::ranked_symbol < > & symbol : tree.getAlphabet ( ) ) {
+	for ( const common::ranked_symbol < SymbolType, RankType > & symbol : tree.getAlphabet ( ) ) {
 		res.addInputSymbol ( symbol );
 		res.setPushdownStoreOperation ( symbol, ext::vector < char > ( 1, S ), ext::vector < char > ( ( size_t ) symbol.getRank ( ), S ) );
 	}
@@ -95,11 +108,11 @@ automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, cha
 	}
 
 	unsigned i = 1;
-	ext::deque < std::pair < size_t, int > > subtreeJumps;
+	ext::deque < std::pair < size_t, unsigned > > subtreeJumps;
 	ext::deque < unsigned > subtreeRepeatsStack;
 
-	ext::vector < common::ranked_symbol < > >::const_iterator rankedSymbolsIter;
-	ext::vector < common::ranked_symbol < unsigned, DefaultRankType > >::const_iterator subtreeRepeatsIter;
+	typename ext::vector < common::ranked_symbol < SymbolType, RankType > >::const_iterator rankedSymbolsIter;
+	typename ext::vector < common::ranked_symbol < unsigned, RankType > >::const_iterator subtreeRepeatsIter;
 	for ( rankedSymbolsIter = tree.getContent ( ).begin(), subtreeRepeatsIter = repeats.getContent ( ).begin ( ); rankedSymbolsIter != tree.getContent ( ).end ( ); ++ rankedSymbolsIter, ++ subtreeRepeatsIter, ++ i ) {
 		common::ranked_symbol < SymbolType, RankType > symbol = * rankedSymbolsIter;
 		subtreeJumps.push_back ( std::make_pair ( ( size_t ) symbol.getRank ( ), i - 1 ) );
@@ -114,18 +127,18 @@ automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, cha
 		res.addTransition ( res.getInitialState ( ), std::move ( symbol ), currentState );
 
 		while ( subtreeJumps.size ( ) && subtreeJumps.back ( ).first == 0 ) {
-			ext::pair < unsigned, unsigned > jumpSource = ext::make_pair ( subtreeJumps.back ( ).second, 0u );
-			res.addTransition ( jumpSource, subtreeWildcard, currentState );
+			ext::pair < unsigned, unsigned > source = ext::make_pair ( subtreeJumps.back ( ).second, 0u );
+			res.addTransition ( source, subtreeWildcard, currentState );
 
 			for ( const common::ranked_symbol < SymbolType, RankType > & nonlinearVariable : nonlinearVariables )
 				if ( nonlinearVariable != currentNonlinearVariable )
-					res.addTransition ( jumpSource, nonlinearVariable, currentState );
+					res.addTransition ( source, nonlinearVariable, currentState );
 				else {
 					unsigned subtreeId = subtreeRepeatsStack.back ( );
 					ext::pair < unsigned, unsigned > targetState = ext::make_pair ( i, subtreeId + 1 );
 
 					res.addState ( targetState );
-					res.addTransition ( jumpSource, nonlinearVariable, targetState );
+					res.addTransition ( source, nonlinearVariable, targetState );
 
 					constructTail ( res, tree, subtreeWildcard, currentNonlinearVariable, nonlinearVariables, subtreeId, rankedSymbolsIter, i, subtreeRepeatsIter );
 				}
@@ -145,6 +158,128 @@ automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, cha
 	return constructInternal ( tree, subtreeWildcard, * nonlinearVariables.begin ( ), nonlinearVariables );
 }
 
+template < class SymbolType, class RankType >
+void ExactNonlinearTreePatternAutomaton::constructTail ( automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > & res, const tree::PrefixRankedBarTree < SymbolType, RankType > & tree, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, const common::ranked_symbol < SymbolType, RankType > & currentNonlinearVariable, const ext::set < common::ranked_symbol < SymbolType, RankType > > & nonlinearVariables, const common::ranked_symbol < SymbolType, RankType > & variablesBar, unsigned subtreeId, typename ext::vector < common::ranked_symbol < SymbolType, RankType > >::const_iterator rankedSymbolsIter, unsigned i, typename ext::vector < common::ranked_symbol < unsigned, RankType > >::const_iterator subtreeRepeatsIter ) {
+	ext::deque < unsigned > subtreeJumps;
+	ext::deque < unsigned > subtreeRepeatsStack;
+
+	for (++ rankedSymbolsIter, ++ subtreeRepeatsIter, ++i; rankedSymbolsIter != tree.getContent ( ).end ( ); ++ rankedSymbolsIter, ++ subtreeRepeatsIter, ++i ) {
+		common::ranked_symbol < SymbolType, RankType > symbol = * rankedSymbolsIter;
+
+		ext::pair < unsigned, unsigned > currentState = ext::make_pair ( i, subtreeId + 1 );
+		ext::pair < unsigned, unsigned > previousState = ext::make_pair ( i - 1, subtreeId + 1 );
+
+		res.addState ( currentState );
+
+		res.addTransition ( previousState, symbol, currentState );
+
+		if ( tree.getBars ( ).count ( symbol ) ) {
+			if ( subtreeJumps.size ( ) ) {
+				ext::pair < unsigned, unsigned > source = ext::make_pair ( subtreeJumps.back ( ), subtreeId + 1 );
+				ext::pair < unsigned, unsigned > middle = ext::make_pair ( ~0 - i, subtreeId + 1 );
+				res.addState ( middle );
+
+				res.addTransition ( source, subtreeWildcard, middle );
+				res.addTransition ( middle, variablesBar, currentState );
+
+				for ( const common::ranked_symbol < SymbolType, RankType > & nonlinearVariable : nonlinearVariables )
+					if ( nonlinearVariable != currentNonlinearVariable || subtreeId == subtreeRepeatsStack.back ( ) )
+						res.addTransition ( source, nonlinearVariable, middle );
+
+				subtreeJumps.pop_back ( );
+				subtreeRepeatsStack.pop_back ( );
+			}
+		} else {
+			subtreeJumps.push_back ( i - 1 );
+			subtreeRepeatsStack.push_back ( subtreeRepeatsIter->getSymbol ( ) );
+		}
+	}
+}
+
+template < class SymbolType, class RankType >
+automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > ExactNonlinearTreePatternAutomaton::constructInternal ( const tree::PrefixRankedBarTree < SymbolType, RankType > & tree, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, const common::ranked_symbol < SymbolType, RankType > & currentNonlinearVariable, const ext::set < common::ranked_symbol < SymbolType, RankType > > & nonlinearVariables, const common::ranked_symbol < SymbolType, RankType > & variablesBar ) {
+	char S = alphabet::SubtreeWildcardSymbol::instance < char > ( );
+	automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > res ( ext::make_pair ( 0u, 0u ), S );
+
+	tree::PrefixRankedBarTree < unsigned, RankType > repeats = tree::properties::ExactSubtreeRepeatsNaive::repeats ( tree );
+
+	for ( const common::ranked_symbol < SymbolType, RankType > & symbol : tree.getAlphabet ( ) ) {
+		res.addInputSymbol ( symbol );
+		if ( tree.getBars ( ).count ( symbol ) )
+			res.setPushdownStoreOperation ( symbol, ext::vector < char > ( 1, S ), ext::vector < char > { } );
+		else
+			res.setPushdownStoreOperation ( symbol, ext::vector < char > { }, ext::vector < char > ( 1, S ) );
+	}
+
+	res.addInputSymbol ( subtreeWildcard );
+	res.setPushdownStoreOperation ( subtreeWildcard, ext::vector < char > ( 1, S ), ext::vector < char > { } );
+
+	res.addInputSymbol ( variablesBar );
+	res.setPushdownStoreOperation ( variablesBar, ext::vector < char > { }, ext::vector < char > ( 1, S ) );
+
+	for ( const common::ranked_symbol < SymbolType, RankType > & nonlinearVariable : nonlinearVariables ) {
+		res.addInputSymbol ( nonlinearVariable );
+		res.setPushdownStoreOperation ( nonlinearVariable, ext::vector < char > ( 1, S ), ext::vector < char > { } );
+	}
+
+	unsigned i = 1;
+	ext::deque < unsigned > subtreeJumps;
+	ext::deque < unsigned > subtreeRepeatsStack;
+
+	typename ext::vector < common::ranked_symbol < SymbolType, RankType > >::const_iterator rankedSymbolsIter;
+	typename ext::vector < common::ranked_symbol < unsigned, RankType > >::const_iterator subtreeRepeatsIter;
+	for ( rankedSymbolsIter = tree.getContent ( ).begin(), subtreeRepeatsIter = repeats.getContent ( ).begin ( ); rankedSymbolsIter != tree.getContent ( ).end ( ); ++ rankedSymbolsIter, ++ subtreeRepeatsIter, ++ i ) {
+		common::ranked_symbol < SymbolType, RankType > symbol = * rankedSymbolsIter;
+
+		ext::pair < unsigned, unsigned > currentState = ext::make_pair ( i, 0u );
+		ext::pair < unsigned, unsigned > previousState = ext::make_pair ( i - 1, 0u );
+
+		res.addState ( currentState );
+
+		res.addTransition ( previousState, symbol, currentState );
+		res.addTransition ( res.getInitialState ( ), symbol, currentState );
+
+		if ( tree.getBars ( ).count ( symbol ) ) {
+			ext::pair < unsigned, unsigned > source = ext::make_pair ( subtreeJumps.back ( ), 0u );
+			ext::pair < unsigned, unsigned > middle = ext::make_pair ( ~0 - i, 0u );
+			res.addState ( middle );
+
+			res.addTransition ( source, subtreeWildcard, middle );
+			res.addTransition ( middle, variablesBar, currentState );
+
+			for ( const common::ranked_symbol < SymbolType, RankType > & nonlinearVariable : nonlinearVariables )
+				if ( nonlinearVariable != currentNonlinearVariable )
+					res.addTransition ( source, nonlinearVariable, middle );
+				else {
+					unsigned subtreeId = subtreeRepeatsStack.back ( );
+					ext::pair < unsigned, unsigned > targetState = ext::make_pair ( i, subtreeId + 1 );
+					ext::pair < unsigned, unsigned > middleState = ext::make_pair ( ~0 - i, subtreeId + 1 );
+
+					res.addState ( targetState );
+					res.addState ( middleState );
+
+					res.addTransition ( source, nonlinearVariable, middleState );
+					res.addTransition ( middleState, variablesBar, targetState );
+
+					constructTail ( res, tree, subtreeWildcard, currentNonlinearVariable, nonlinearVariables, variablesBar, subtreeId, rankedSymbolsIter, i, subtreeRepeatsIter );
+				}
+
+			subtreeJumps.pop_back ( );
+			subtreeRepeatsStack.pop_back ( );
+		} else {
+			subtreeJumps.push_back ( i - 1 );
+			subtreeRepeatsStack.push_back ( subtreeRepeatsIter->getSymbol ( ) );
+		}
+	}
+
+	return res;
+}
+
+template < class SymbolType, class RankType >
+automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > ExactNonlinearTreePatternAutomaton::construct ( const tree::PrefixRankedBarTree < SymbolType, RankType > & tree, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, const ext::set < common::ranked_symbol < SymbolType, RankType > > & nonlinearVariables, const common::ranked_symbol < SymbolType, RankType > & variablesBar ) {
+	return constructInternal ( tree, subtreeWildcard, * nonlinearVariables.begin ( ), nonlinearVariables, variablesBar );
+}
+
 } /* namespace exact */
 
 } /* namespace arbology */
-- 
GitLab