diff --git a/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.cpp b/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.cpp index 99fb225cacd1da62de18747b28d17f457891d90d..bf4cb98f0d50b65c24c1bcc9520c308494baec3b 100644 --- a/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.cpp +++ b/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.cpp @@ -6,183 +6,23 @@ */ #include "ExactPatternMatchingAutomaton.h" -#include "ExactSubtreeMatchingAutomaton.h" -#include <tree/properties/SubtreeJumpTable.h> - -#include <tree/ranked/RankedTree.h> -#include <tree/ranked/RankedPattern.h> -#include <tree/ranked/PrefixRankedTree.h> -#include <tree/ranked/PrefixRankedPattern.h> -#include <tree/ranked/PrefixRankedBarTree.h> -#include <tree/ranked/PrefixRankedBarPattern.h> - -#include <automaton/PDA/InputDrivenNPDA.h> -#include <automaton/PDA/VisiblyPushdownNPDA.h> -#include <automaton/PDA/NPDA.h> -#include <automaton/TA/NFTA.h> - -#include <alib/deque> -#include <alphabet/RankedSymbol.h> #include <registration/AlgoRegistration.hpp> namespace arbology { namespace exact { -automaton::InputDrivenNPDA < > ExactPatternMatchingAutomaton::construct ( const tree::PrefixRankedTree < > & pattern ) { - return ExactSubtreeMatchingAutomaton::construct ( pattern ); -} - -auto ExactPatternMatchingAutomatonPrefixRankedTree = registration::AbstractRegister < ExactPatternMatchingAutomaton, automaton::InputDrivenNPDA < >, const tree::PrefixRankedTree < > & > ( ExactPatternMatchingAutomaton::construct ); - -ext::vector < DefaultSymbolType > computeRHS ( const tree::PrefixRankedPattern < > & pattern, const ext::vector < int > & patternSubtreeJumpTable, int i ) { - const ext::vector < common::ranked_symbol < > > & content = pattern.getContent ( ); - - unsigned rank = ( unsigned ) content[i].getRank ( ); - - i++; - - ext::vector < DefaultSymbolType > res; - - for ( unsigned ranki = 0; ranki < rank; ranki++ ) { - if ( content[i] == pattern.getSubtreeWildcard ( ) ) { - res.push_back ( DefaultSymbolType ( 'R' ) ); - i++; - } else { - res.push_back ( DefaultSymbolType ( 'T' ) ); - - i = patternSubtreeJumpTable[i]; - } - } - - return res; -} - -automaton::NPDA < > ExactPatternMatchingAutomaton::construct ( const tree::PrefixRankedPattern < > & pattern ) { - automaton::NPDA < > res ( DefaultStateType ( 0 ), DefaultSymbolType ( 'T' ) ); - - for ( const common::ranked_symbol < > & symbol : pattern.getAlphabet ( ) ) { - if ( symbol == pattern.getSubtreeWildcard ( ) ) continue; - - res.addInputSymbol ( DefaultSymbolType ( alphabet::RankedSymbol < > { symbol } ) ); - } - - res.setPushdownStoreAlphabet ( { DefaultSymbolType ( 'T' ), DefaultSymbolType ( 'R' ) } ); - - for ( const common::ranked_symbol < > & symbol : pattern.getAlphabet ( ) ) { - if ( symbol == pattern.getSubtreeWildcard ( ) ) continue; - - res.addTransition ( DefaultStateType ( 0 ), DefaultSymbolType ( alphabet::RankedSymbol < > { symbol } ), ext::vector < DefaultSymbolType > ( 1, DefaultSymbolType ( 'T' ) ), DefaultStateType ( 0 ), ext::vector < DefaultSymbolType > ( ( size_t ) symbol.getRank ( ), DefaultSymbolType ( 'T' ) ) ); - } - - ext::vector < int > patternSubtreeJumpTable = tree::properties::SubtreeJumpTable::compute ( pattern ); - - int i = 1; - - for ( const common::ranked_symbol < > & symbol : pattern.getContent ( ) ) { - res.addState ( DefaultStateType ( i ) ); - - if ( symbol == pattern.getSubtreeWildcard ( ) ) - for ( const common::ranked_symbol < > & alphabetSymbol : pattern.getAlphabet ( ) ) { - if ( alphabetSymbol == pattern.getSubtreeWildcard ( ) ) continue; - - if ( ( unsigned ) alphabetSymbol.getRank ( ) == 0 ) { - res.addTransition ( DefaultStateType ( i - 1 ), DefaultSymbolType ( alphabet::RankedSymbol < > { alphabetSymbol } ), ext::vector < DefaultSymbolType > ( 1, DefaultSymbolType ( 'T' ) ), DefaultStateType ( i - 1 ), ext::vector < DefaultSymbolType > { } ); - - res.addTransition ( DefaultStateType ( i - 1 ), DefaultSymbolType ( alphabet::RankedSymbol < > { alphabetSymbol } ), ext::vector < DefaultSymbolType > ( 1, DefaultSymbolType ( 'R' ) ), DefaultStateType ( i ), ext::vector < DefaultSymbolType > { } ); - } else { - ext::vector < DefaultSymbolType > push ( ( unsigned ) alphabetSymbol.getRank ( ), DefaultSymbolType ( 'T' ) ); - res.addTransition ( DefaultStateType ( i - 1 ), DefaultSymbolType ( alphabet::RankedSymbol < > { alphabetSymbol } ), ext::vector < DefaultSymbolType > ( 1, DefaultSymbolType ( 'T' ) ), DefaultStateType ( i - 1 ), push ); +auto ExactPatternMatchingAutomatonPrefixRankedTree = registration::AbstractRegister < ExactPatternMatchingAutomaton, automaton::InputDrivenNPDA < common::ranked_symbol < DefaultSymbolType, DefaultRankType >, char, unsigned >, const tree::PrefixRankedTree < > & > ( ExactPatternMatchingAutomaton::construct ); - push[ ( unsigned ) alphabetSymbol.getRank ( ) - 1] = DefaultSymbolType ( 'R' ); - res.addTransition ( DefaultStateType ( i - 1 ), DefaultSymbolType ( alphabet::RankedSymbol < > { alphabetSymbol } ), ext::vector < DefaultSymbolType > ( 1, DefaultSymbolType ( 'R' ) ), DefaultStateType ( i - 1 ), push ); - } - } +auto ExactPatternMatchingAutomatonPrefixRankedPattern = registration::AbstractRegister < ExactPatternMatchingAutomaton, automaton::NPDA < common::ranked_symbol < DefaultSymbolType, DefaultRankType >, DefaultEpsilonType, char, unsigned >, const tree::PrefixRankedPattern < > & > ( ExactPatternMatchingAutomaton::construct ); - else - res.addTransition ( DefaultStateType ( i - 1 ), DefaultSymbolType ( alphabet::RankedSymbol < > { symbol } ), ext::vector < DefaultSymbolType > ( 1, DefaultSymbolType ( 'T' ) ), DefaultStateType ( i ), computeRHS ( pattern, patternSubtreeJumpTable, i - 1 ) ); - - i++; - } - - res.addFinalState ( DefaultStateType ( i - 1 ) ); - return res; -} - -auto ExactPatternMatchingAutomatonPrefixRankedPattern = registration::AbstractRegister < ExactPatternMatchingAutomaton, automaton::NPDA < >, const tree::PrefixRankedPattern < > & > ( ExactPatternMatchingAutomaton::construct ); - -automaton::InputDrivenNPDA < > ExactPatternMatchingAutomaton::construct ( const tree::PrefixRankedBarTree < > & pattern ) { - return ExactSubtreeMatchingAutomaton::construct ( pattern ); -} - -auto ExactPatternMatchingAutomatonPrefixRankedBarTree = registration::AbstractRegister < ExactPatternMatchingAutomaton, automaton::InputDrivenNPDA < >, const tree::PrefixRankedBarTree < > & > ( ExactPatternMatchingAutomaton::construct ); +auto ExactPatternMatchingAutomatonPrefixRankedBarTree = registration::AbstractRegister < ExactPatternMatchingAutomaton, automaton::InputDrivenNPDA < common::ranked_symbol < DefaultSymbolType, DefaultRankType >, char, unsigned >, const tree::PrefixRankedBarTree < > & > ( ExactPatternMatchingAutomaton::construct ); auto ExactPatternMatchingAutomatonPrefixRankedBarPattern = registration::AbstractRegister < ExactPatternMatchingAutomaton, automaton::VisiblyPushdownNPDA < common::ranked_symbol < DefaultSymbolType, DefaultRankType >, char, unsigned >, const tree::PrefixRankedBarPattern < > & > ( ExactPatternMatchingAutomaton::construct ); -automaton::NFTA < > ExactPatternMatchingAutomaton::construct ( const tree::RankedTree < > & pattern ) { - return ExactSubtreeMatchingAutomaton::construct ( pattern ); -} - -auto ExactPatternMatchingAutomatonRankedTree = registration::AbstractRegister < ExactPatternMatchingAutomaton, automaton::NFTA < >, const tree::RankedTree < > & > ( ExactPatternMatchingAutomaton::construct ); - -DefaultStateType constructRecursivePattern ( const ext::tree < common::ranked_symbol < > > & node, automaton::NFTA < > & res, const common::ranked_symbol < > & subtreeWildcard, const DefaultStateType & loopState, int & nextState ) { - if ( node.getData ( ) == subtreeWildcard ) { - DefaultStateType state = DefaultStateType ( nextState++ ); - res.addState ( state ); - - for ( const common::ranked_symbol < > & symbol : res.getInputAlphabet ( ) ) { - ext::vector < DefaultStateType > states; - states.reserve ( ( size_t ) symbol.getRank ( ) ); - - for ( unsigned i = 0; i < ( unsigned ) symbol.getRank ( ); i++ ) - states.push_back ( loopState ); - - res.addTransition ( symbol, states, state ); - } - - return state; - } else { - ext::vector < DefaultStateType > states; - states.reserve ( ( size_t ) node.getData ( ).getRank ( ) ); - - for ( const ext::tree < common::ranked_symbol < > > & child : node.getChildren ( ) ) - states.push_back ( constructRecursivePattern ( child, res, subtreeWildcard, loopState, nextState ) ); - - DefaultStateType state = DefaultStateType ( nextState++ ); - res.addState ( state ); - res.addTransition ( node.getData ( ), states, state ); - return state; - } -} - -automaton::NFTA < > ExactPatternMatchingAutomaton::construct ( const tree::RankedPattern < > & pattern ) { - ext::set < common::ranked_symbol < > > alphabet = pattern.getAlphabet ( ); - - alphabet.erase ( pattern.getSubtreeWildcard ( ) ); - - automaton::NFTA < > res; - res.setInputAlphabet ( alphabet ); - - int nextState = 0; - - DefaultStateType loopState = DefaultStateType ( nextState++ ); - res.addState ( loopState ); - - for ( const common::ranked_symbol < > & symbol : res.getInputAlphabet ( ) ) { - ext::vector < DefaultStateType > states; - states.reserve ( ( size_t ) symbol.getRank ( ) ); - - for ( unsigned i = 0; i < ( unsigned ) symbol.getRank ( ); i++ ) - states.push_back ( loopState ); - - res.addTransition ( symbol, states, loopState ); - } - - res.addFinalState ( constructRecursivePattern ( pattern.getContent ( ), res, pattern.getSubtreeWildcard ( ), loopState, nextState ) ); - return res; -} +auto ExactPatternMatchingAutomatonRankedTree = registration::AbstractRegister < ExactPatternMatchingAutomaton, automaton::NFTA < DefaultSymbolType, DefaultRankType, unsigned >, const tree::RankedTree < > & > ( ExactPatternMatchingAutomaton::construct ); -auto ExactPatternMatchingAutomatonRankedPattern = registration::AbstractRegister < ExactPatternMatchingAutomaton, automaton::NFTA < >, const tree::RankedPattern < > & > ( ExactPatternMatchingAutomaton::construct ); +auto ExactPatternMatchingAutomatonRankedPattern = registration::AbstractRegister < ExactPatternMatchingAutomaton, automaton::NFTA < DefaultSymbolType, DefaultRankType, unsigned >, const tree::RankedPattern < > & > ( ExactPatternMatchingAutomaton::construct ); } /* namespace exact */ diff --git a/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.h b/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.h index 62ef9efb8189a36c2fa315dce3bcf2dcd29a5130..fef8226221e4ce6d4fb5483e2a460feacdd771b0 100644 --- a/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.h +++ b/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.h @@ -8,9 +8,23 @@ #ifndef _EXACT_PATTERN_MATCHING_AUTOMATON_H__ #define _EXACT_PATTERN_MATCHING_AUTOMATON_H__ -#include <automaton/AutomatonFeatures.h> -#include <tree/TreeFeatures.h> +#include "ExactSubtreeMatchingAutomaton.h" +#include <tree/properties/SubtreeJumpTable.h> + +#include <tree/ranked/RankedTree.h> +#include <tree/ranked/RankedPattern.h> +#include <tree/ranked/PrefixRankedTree.h> +#include <tree/ranked/PrefixRankedPattern.h> +#include <tree/ranked/PrefixRankedBarTree.h> +#include <tree/ranked/PrefixRankedBarPattern.h> + +#include <automaton/PDA/InputDrivenNPDA.h> +#include <automaton/PDA/VisiblyPushdownNPDA.h> +#include <automaton/PDA/NPDA.h> +#include <automaton/TA/NFTA.h> + +#include <common/ranked_symbol.hpp> #include <alphabet/BottomOfTheStackSymbol.h> namespace arbology { @@ -23,16 +37,108 @@ public: * Performs conversion. * @return left regular grammar equivalent to source automaton. */ - static automaton::NPDA < > construct ( const tree::PrefixRankedPattern < > & pattern ); - static automaton::InputDrivenNPDA < > construct ( const tree::PrefixRankedTree < > & pattern ); + template < class SymbolType, class RankType > + static automaton::NPDA < common::ranked_symbol < SymbolType, RankType >, DefaultEpsilonType, char, unsigned> construct ( const tree::PrefixRankedPattern < SymbolType, RankType > & pattern ); + + template < class SymbolType, class RankType > + static automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, unsigned > construct ( const tree::PrefixRankedTree < SymbolType, RankType > & pattern ); + template < class SymbolType, class RankType > static automaton::VisiblyPushdownNPDA < common::ranked_symbol < SymbolType, RankType >, char, unsigned > construct ( const tree::PrefixRankedBarPattern < SymbolType, RankType > & pattern ); - static automaton::InputDrivenNPDA < > construct ( const tree::PrefixRankedBarTree < > & pattern ); - static automaton::NFTA < > construct ( const tree::RankedTree < > & pattern ); - static automaton::NFTA < > construct ( const tree::RankedPattern < > & pattern ); + + template < class SymbolType, class RankType > + static automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, unsigned > construct ( const tree::PrefixRankedBarTree < SymbolType, RankType > & pattern ); + + template < class SymbolType, class RankType > + static automaton::NFTA < SymbolType, RankType, unsigned > construct ( const tree::RankedTree < SymbolType, RankType > & pattern ); + + template < class SymbolType, class RankType > + static automaton::NFTA < SymbolType, RankType, unsigned > construct ( const tree::RankedPattern < SymbolType, RankType > & pattern ); }; +template < class SymbolType, class RankType > +ext::vector < char > computeRHS ( const tree::PrefixRankedPattern < SymbolType, RankType > & pattern, const ext::vector < int > & patternSubtreeJumpTable, int i ) { + const ext::vector < common::ranked_symbol < SymbolType, RankType > > & content = pattern.getContent ( ); + + unsigned rank = ( unsigned ) content [ i ].getRank ( ); + + i++; + + ext::vector < char > res; + + for ( unsigned ranki = 0; ranki < rank; ranki++ ) { + if ( content [ i ] == pattern.getSubtreeWildcard ( ) ) { + res.push_back ( 'R' ); + i++; + } else { + res.push_back ( 'T' ); + + i = patternSubtreeJumpTable [ i ]; + } + } + + return res; +} + +template < class SymbolType, class RankType > +automaton::NPDA < common::ranked_symbol < SymbolType, RankType >, DefaultEpsilonType, char, unsigned > ExactPatternMatchingAutomaton::construct ( const tree::PrefixRankedPattern < SymbolType, RankType > & pattern ) { + automaton::NPDA < common::ranked_symbol < SymbolType, RankType >, DefaultEpsilonType, char, unsigned > res ( 0, 'T' ); + + for ( const common::ranked_symbol < SymbolType, RankType > & symbol : pattern.getAlphabet ( ) ) { + if ( symbol == pattern.getSubtreeWildcard ( ) ) continue; + + res.addInputSymbol ( symbol ); + } + + res.setPushdownStoreAlphabet ( { 'T', 'R' } ); + + for ( const common::ranked_symbol < SymbolType, RankType > & symbol : pattern.getAlphabet ( ) ) { + if ( symbol == pattern.getSubtreeWildcard ( ) ) continue; + + res.addTransition ( 0, symbol, ext::vector < char > ( 1, 'T' ), 0, ext::vector < char > ( ( size_t ) symbol.getRank ( ), 'T' ) ); + } + + ext::vector < int > patternSubtreeJumpTable = tree::properties::SubtreeJumpTable::compute ( pattern ); + + unsigned i = 1; + + for ( const common::ranked_symbol < SymbolType, RankType > & symbol : pattern.getContent ( ) ) { + res.addState ( i ); + + if ( symbol == pattern.getSubtreeWildcard ( ) ) + for ( const common::ranked_symbol < SymbolType, RankType > & alphabetSymbol : pattern.getAlphabet ( ) ) { + if ( alphabetSymbol == pattern.getSubtreeWildcard ( ) ) continue; + + if ( ( unsigned ) alphabetSymbol.getRank ( ) == 0 ) { + res.addTransition ( i - 1, alphabetSymbol, ext::vector < char > ( 1, 'T' ), i - 1, ext::vector < char > { } ); + + res.addTransition ( i - 1, alphabetSymbol, ext::vector < char > ( 1, 'R' ), i, ext::vector < char > { } ); + } else { + ext::vector < char > push ( ( unsigned ) alphabetSymbol.getRank ( ), 'T' ); + res.addTransition ( i - 1, alphabetSymbol, ext::vector < char > ( 1, 'T' ), i - 1, push ); + + push [ ( unsigned ) alphabetSymbol.getRank ( ) - 1 ] = 'R'; + res.addTransition ( i - 1, alphabetSymbol, ext::vector < char > ( 1, 'R' ), i - 1, push ); + } + } + + else + res.addTransition ( i - 1, symbol, ext::vector < char > ( 1, 'T' ), i, computeRHS ( pattern, patternSubtreeJumpTable, i - 1 ) ); + + i++; + } + + res.addFinalState ( i - 1 ); + + return res; +} + +template < class SymbolType, class RankType > +automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, unsigned > ExactPatternMatchingAutomaton::construct ( const tree::PrefixRankedTree < SymbolType, RankType > & pattern ) { + return ExactSubtreeMatchingAutomaton::construct ( pattern ); +} + template < class SymbolType, class RankType > automaton::VisiblyPushdownNPDA < common::ranked_symbol < SymbolType, RankType >, char, unsigned > ExactPatternMatchingAutomaton::construct ( const tree::PrefixRankedBarPattern < SymbolType, RankType > & pattern ) { automaton::VisiblyPushdownNPDA < common::ranked_symbol < SymbolType, RankType >, char, unsigned > res ( alphabet::BottomOfTheStackSymbol::instance < char > ( ) ); @@ -99,6 +205,75 @@ automaton::VisiblyPushdownNPDA < common::ranked_symbol < SymbolType, RankType >, return res; } +template < class SymbolType, class RankType > +automaton::InputDrivenNPDA < common::ranked_symbol < SymbolType, RankType >, char, unsigned > ExactPatternMatchingAutomaton::construct ( const tree::PrefixRankedBarTree < SymbolType, RankType > & pattern ) { + return ExactSubtreeMatchingAutomaton::construct ( pattern ); +} + +template < class SymbolType, class RankType > +automaton::NFTA < SymbolType, RankType, unsigned > ExactPatternMatchingAutomaton::construct ( const tree::RankedTree < SymbolType, RankType > & pattern ) { + return ExactSubtreeMatchingAutomaton::construct ( pattern ); +} + +template < class SymbolType, class RankType > +unsigned constructRecursivePattern ( const ext::tree < common::ranked_symbol < SymbolType, RankType > > & node, automaton::NFTA < SymbolType, RankType, unsigned > & res, const common::ranked_symbol < SymbolType, RankType > & subtreeWildcard, unsigned loopState, unsigned & nextState ) { + if ( node.getData ( ) == subtreeWildcard ) { + unsigned state = nextState++; + res.addState ( state ); + + for ( const common::ranked_symbol < SymbolType, RankType > & symbol : res.getInputAlphabet ( ) ) { + ext::vector < unsigned > states; + states.reserve ( ( size_t ) symbol.getRank ( ) ); + + for ( unsigned i = 0; i < ( unsigned ) symbol.getRank ( ); i++ ) + states.push_back ( loopState ); + + res.addTransition ( symbol, states, state ); + } + + return state; + } else { + ext::vector < unsigned > states; + states.reserve ( ( size_t ) node.getData ( ).getRank ( ) ); + + for ( const ext::tree < common::ranked_symbol < SymbolType, RankType > > & child : node.getChildren ( ) ) + states.push_back ( constructRecursivePattern ( child, res, subtreeWildcard, loopState, nextState ) ); + + unsigned state = nextState++; + res.addState ( state ); + res.addTransition ( node.getData ( ), states, state ); + return state; + } +} + +template < class SymbolType, class RankType > +automaton::NFTA < SymbolType, RankType, unsigned > ExactPatternMatchingAutomaton::construct ( const tree::RankedPattern < SymbolType, RankType > & pattern ) { + ext::set < common::ranked_symbol < SymbolType, RankType> > alphabet = pattern.getAlphabet ( ); + + alphabet.erase ( pattern.getSubtreeWildcard ( ) ); + + automaton::NFTA < SymbolType, RankType, unsigned > res; + res.setInputAlphabet ( alphabet ); + + unsigned nextState = 0; + + unsigned loopState = nextState++; + res.addState ( loopState ); + + for ( const common::ranked_symbol < SymbolType, RankType > & symbol : res.getInputAlphabet ( ) ) { + ext::vector < unsigned > states; + states.reserve ( ( size_t ) symbol.getRank ( ) ); + + for ( unsigned i = 0; i < ( unsigned ) symbol.getRank ( ); i++ ) + states.push_back ( loopState ); + + res.addTransition ( symbol, states, loopState ); + } + + res.addFinalState ( constructRecursivePattern ( pattern.getContent ( ), res, pattern.getSubtreeWildcard ( ), loopState, nextState ) ); + return res; +} + } /* namespace exact */ } /* namespace arbology */