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