Skip to content
Snippets Groups Projects
ExactNonlinearTreePatternAutomaton.h 8.72 KiB
Newer Older
/*
 * ExactNonlinearTreePatternAutomaton.h
 *
 *  Created on: 7. 4. 2015
 *      Author: Jan Travnicek
 */

#ifndef _EXACT_NONLINEAR_TREE_PATTERN_AUTOMATON_H__
#define _EXACT_NONLINEAR_TREE_PATTERN_AUTOMATON_H__

#include <alib/pair>
#include <alib/deque>
#include <alib/vector>
Jan Trávníček's avatar
Jan Trávníček committed
#include <common/ranked_symbol.hpp>
#include <tree/ranked/PrefixRankedTree.h>
#include <automaton/PDA/InputDrivenNPDA.h>

#include <tree/properties/ExactSubtreeRepeatsNaive.h>

class ExactNonlinearTreePatternAutomaton {
	template < class SymbolType, class RankType >
	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 );

public:
	/**
	 * 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::PrefixRankedTree < SymbolType, RankType > & tree, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, const ext::set < common::ranked_symbol < SymbolType, RankType > > & nonlinearVariables );
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;
	ext::deque < unsigned > subtreeRepeatsStack;

	for (++ rankedSymbolsIter, ++ subtreeRepeatsIter, ++i; 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 ) );
		subtreeRepeatsStack.push_back ( subtreeRepeatsIter->getSymbol ( ) );

		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, 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 );

			for ( const common::ranked_symbol < SymbolType, RankType > & nonlinearVariable : nonlinearVariables )
				if ( nonlinearVariable != currentNonlinearVariable || subtreeId == subtreeRepeatsStack.back ( ) )
					res.addTransition ( jumpSource, nonlinearVariable, currentState );

			if ( subtreeJumps.size ( ) ) {
				subtreeJumps.pop_back ( );
				subtreeRepeatsStack.pop_back ( );
			}
		}

		if ( subtreeJumps.size ( ) ) subtreeJumps.back ( ).first--;
	}
}

template < class SymbolType, class RankType >
automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > ExactNonlinearTreePatternAutomaton::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 ) {
	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 );

	for ( const common::ranked_symbol < > & symbol : tree.getAlphabet ( ) ) {
		res.addInputSymbol ( symbol );
		res.setPushdownStoreOperation ( symbol, ext::vector < char > ( 1, S ), ext::vector < char > ( ( size_t ) symbol.getRank ( ), S ) );
	}

	res.addInputSymbol ( subtreeWildcard );
	res.setPushdownStoreOperation ( subtreeWildcard, ext::vector < char > ( 1, S ), ext::vector < char > { } );

	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 < std::pair < size_t, int > > subtreeJumps;
	ext::deque < unsigned > subtreeRepeatsStack;

	ext::vector < common::ranked_symbol < > >::const_iterator rankedSymbolsIter;
	ext::vector < common::ranked_symbol < unsigned, DefaultRankType > >::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 ) );
		subtreeRepeatsStack.push_back ( subtreeRepeatsIter->getSymbol ( ) );

		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 ( ), 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 );

			for ( const common::ranked_symbol < SymbolType, RankType > & nonlinearVariable : nonlinearVariables )
				if ( nonlinearVariable != currentNonlinearVariable )
					res.addTransition ( jumpSource, 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 );

					constructTail ( res, tree, subtreeWildcard, currentNonlinearVariable, nonlinearVariables, subtreeId, rankedSymbolsIter, i, subtreeRepeatsIter );
				}

			subtreeJumps.pop_back ( );
			subtreeRepeatsStack.pop_back ( );
		}

		if ( subtreeJumps.size ( ) ) subtreeJumps.back ( ).first--;
	}

	return res;
}

template < class SymbolType, class RankType >
automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, ext::pair < unsigned, unsigned > > ExactNonlinearTreePatternAutomaton::construct ( const tree::PrefixRankedTree < SymbolType, RankType > & tree, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, const ext::set < common::ranked_symbol < SymbolType, RankType > > & nonlinearVariables ) {
	return constructInternal ( tree, subtreeWildcard, * nonlinearVariables.begin ( ), nonlinearVariables );
}

} /* namespace exact */

} /* namespace arbology */

#endif /* _EXACT_NONLINEAR_TREE_PATTERN_AUTOMATON_H__ */