From 3c35610185abf62d9ded2a49e2e9404614a087cb Mon Sep 17 00:00:00 2001 From: Tomas Pecka <peckato1@fit.cvut.cz> Date: Sun, 6 Aug 2017 16:39:13 +0200 Subject: [PATCH] GlushkovRTE: Split Follow and SubstMap compute. Fix generating transitions. --- .../ToPostfixPushdownAutomatonGlushkovV3.cpp | 93 ++++----- alib2algo/src/rte/glushkov/GlushkovFollowV3.h | 119 +++--------- .../rte/glushkov/GlushkovSubstitutionMap.h | 176 ++++++++++++++++++ 3 files changed, 241 insertions(+), 147 deletions(-) create mode 100644 alib2algo/src/rte/glushkov/GlushkovSubstitutionMap.h diff --git a/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovV3.cpp b/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovV3.cpp index 360c13bc89..b3cec97de8 100644 --- a/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovV3.cpp +++ b/alib2algo/src/rte/convert/ToPostfixPushdownAutomatonGlushkovV3.cpp @@ -17,6 +17,7 @@ #include "../glushkov/GlushkovFollowV3.h" #include "../glushkov/GlushkovIndexate.h" #include "../glushkov/GlushkovFirst.h" +#include "../glushkov/GlushkovSubstitutionMap.h" namespace rte { @@ -45,10 +46,11 @@ ToPostfixPushdownAutomatonGlushkovV3::convert ( const rte::FormalRTE < > & rte ) const std::set < std::ranked_symbol < > > firstSet = rte::GlushkovFirst::first ( indexedRTE ); // - follow set for every element of (non-indexed) RTE alphabet element + const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, std::map < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > > substMapTree = GlushkovSubstitutionMap::substMap ( indexedRTE ); std::map < std::ranked_symbol < >, std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > > followSet; for ( const std::ranked_symbol < > & symbol : indexedRTE.getAlphabet ( ) ) - followSet.insert ( std::make_pair ( symbol, rte::GlushkovFollowV3::follow ( indexedRTE, symbol ) ) ); + followSet.insert ( std::make_pair ( symbol, rte::GlushkovFollowV3::follow ( indexedRTE, symbol, substMapTree ) ) ); /* check for exceptions -> there must be NO substitution symbol in first set */ if ( isSubstSymbolPresent ( firstSet, rte.getSubstitutionAlphabet ( ) ) ) @@ -85,10 +87,10 @@ ToPostfixPushdownAutomatonGlushkovV3::convert ( const rte::FormalRTE < > & rte ) automaton.addPushdownStoreSymbol ( std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > ( { symb } ) ); // complex - for ( const std::pair < const std::ranked_symbol < >, std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > >& kv : followSet ) { - for ( const GlushkovFollowV3::TFollowTuple < SymbolType, RankType > & followTuple : kv.second ) { - for ( const std::set < std::ranked_symbol < > > & symb : followTuple ) { - automaton.addPushdownStoreSymbol ( std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > ( symb ) ); + for ( const std::pair < const rte::FormalRTEElement < SymbolType, RankType >* const, std::map < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > > & kv : substMapTree ) { + if ( dynamic_cast < const rte::FormalRTESymbolSubst < SymbolType, RankType > * const > ( kv.first ) ) { + for ( const std::pair < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > & kv2 : kv.second ) { + automaton.addPushdownStoreSymbol ( kv2.second ); } } } @@ -145,13 +147,13 @@ ToPostfixPushdownAutomatonGlushkovV3::convert ( const rte::FormalRTE < > & rte ) std::vector < std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > > push; push.push_back( std::set < std::ranked_symbol < SymbolType, RankType > > { symb } ); - automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), { }, q, push ); if ( common::GlobalData::verbose ) { std::cerr << "Transition 3: " << rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ) << " | " << std::endl << "\t" << "[]" << std::endl << "\t ->" << std::endl << "\t" << push << std::endl << std::endl; } + automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), { }, q, push ); } else { for ( const GlushkovFollowV3::TFollowTuple < SymbolType, RankType > & followTuple : followSet [ symb ] ) { //tuple = vector < set < symb > > std::vector < std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > > pop, push; @@ -159,77 +161,52 @@ ToPostfixPushdownAutomatonGlushkovV3::convert ( const rte::FormalRTE < > & rte ) /* for ( const auto & e : symbFollowTuple ) pop.push_back ( e ); - std::reverse ( pop.begin ( ), pop.end ( ) ); // <------------ WTF. CRASHES HERE + std::reverse ( pop.begin ( ), pop.end ( ) ); // <------------ WTF. CRASHES HERE // FIXME */ for ( const auto & e : followTuple ) pop.insert ( pop.begin ( ), e ); push.push_back( std::set < std::ranked_symbol < SymbolType, RankType > > { symb } ); - automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), pop, q, push ); if ( common::GlobalData::verbose ) { std::cerr << "Transition 2: " << rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ) << " | " << std::endl << "\t" << pop << std::endl << "\t ->" << std::endl << "\t" << push << std::endl << std::endl; } + automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), pop, q, push ); } } } // Pattern 1 for ( const std::ranked_symbol < > & symb : indexedRTE.getAlphabet ( ) ) { - // 1a - if ( symb.getRank ( ) == primitive::Unsigned ( 0 ) ) { - /* If symb \in some symbolSet of followSet [ i ], then symb | \varepsilon -> symbolSet */ - - for ( const std::pair < const std::ranked_symbol < >, std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > >& kv : followSet ) { - for ( const GlushkovFollowV3::TFollowTuple < SymbolType, RankType > & followTuple : kv.second ) { // TFollowTuple = vector < set < ranked_symbol > > - for ( const std::set < std::ranked_symbol < > > & symbolSet : followTuple ) { - if ( symbolSet.count ( symb ) ) { - std::vector < std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > > push; - push.push_back( symbolSet ); - automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), { }, q, push ); - - if ( common::GlobalData::verbose ) { - std::cerr << "Transition 1a: " << rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ) << " | " << std::endl << - "\t" << "[ ]" << std::endl << - "\t ->" << std::endl << - "\t" << push << std::endl << std::endl; - } - } + for ( const std::pair < const rte::FormalRTEElement < SymbolType, RankType >* const, std::map < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > > & kv : substMapTree ) { + if ( dynamic_cast < const rte::FormalRTESymbolSubst < SymbolType, RankType > * const > ( kv.first ) == nullptr ) // not a SubstSymbol node + continue; + + for ( const std::pair < std::ranked_symbol < >, std::set < std::ranked_symbol < > > > & kv2 : kv.second ) { + if ( kv2.second.count ( symb ) == 0 ) + continue; + + for ( const GlushkovFollowV3::TFollowTuple < SymbolType, RankType > & symbFollowTuple : followSet [ symb ] ) { + std::vector < std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > > pop, push; + + if ( ( size_t ) symb.getRank ( ) > 0 ) { + for ( const auto & e : symbFollowTuple ) + pop.insert ( pop.begin ( ), e ); } - } - } - } else { // 1b - /* If symb \in some symbolSet of followSet [ i ], then symb | followTuple -> symbolSet */ - for ( const std::pair < const std::ranked_symbol < >, std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > >& kv : followSet ) { - for ( const GlushkovFollowV3::TFollowTuple < SymbolType, RankType > & followTuple : kv.second ) { // TFollowTuple = vector < set < ranked_symbol > > - for ( const std::set < std::ranked_symbol < > > & symbolSet : followTuple ) { - if ( symbolSet.count ( symb ) ) { - std::vector < std::variant < alphabet::BottomOfTheStackSymbol, std::set < std::ranked_symbol < SymbolType, RankType > > > > pop, push; - - for ( const GlushkovFollowV3::TFollowTuple < SymbolType, RankType > & symbFollowTuple : followSet [ symb ] ) { - /* - for ( const auto & e : symbFollowTuple ) - pop.push_back ( e ); - std::reverse ( pop.begin ( ), pop.end ( ) ); // <------------ WTF. CRASHES HERE - */ - for ( const auto & e : symbFollowTuple ) - pop.insert ( pop.begin ( ), e ); - - push.push_back( symbolSet ); - automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), pop, q, push ); - - if ( common::GlobalData::verbose ) { - std::cerr << "Transition 1b: " << rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ) << " | " << std::endl << - "\t" << pop << std::endl << - "\t ->" << std::endl << - "\t" << push << std::endl << std::endl; - } - } - } + + push.push_back( kv2.second ); + + if ( common::GlobalData::verbose ) { + std::cerr << "Transition 1" << ( pop.empty() ? "a" : "b" ) << ": " << rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ) << " | " << std::endl << + "\t" << pop << std::endl << + "\t ->" << std::endl << + "\t" << push << std::endl << std::endl; } + + automaton.addTransition ( q, rte::GlushkovIndexate::getSymbolFromGlushkovPair ( symb ).getSymbol ( ), pop, q, push ); } } } @@ -242,8 +219,6 @@ ToPostfixPushdownAutomatonGlushkovV3::convert ( const rte::FormalRTE < > & rte ) pop.push_back ( BotS ); automaton.addTransition ( q, alphabet::EndSymbol::instance < DefaultSymbolType > ( ), pop, f, { } ); } - - /* TRANSITIONS END */ return automaton; diff --git a/alib2algo/src/rte/glushkov/GlushkovFollowV3.h b/alib2algo/src/rte/glushkov/GlushkovFollowV3.h index 052e245395..4c33e1f33f 100644 --- a/alib2algo/src/rte/glushkov/GlushkovFollowV3.h +++ b/alib2algo/src/rte/glushkov/GlushkovFollowV3.h @@ -44,120 +44,69 @@ private: template < class SymbolType, class RankType > static std::set < TFollowTuple < SymbolType, RankType > > replaceConstants ( const TAlphabet < SymbolType, RankType > & alphabetK, const std::vector < std::ranked_symbol < SymbolType, RankType > > & follow, const TSubstMap < SymbolType, RankType > & subMap2 ); - template < class SymbolType, class RankType > - static void preprocessSubMap ( const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ); - - template < class T > - static std::vector < std::vector < T > > cartesian ( const std::vector < std::vector < T > > & input ); - - template < class T > - static void cartesian_rec ( const std::vector < std::vector < T > > & input, std::vector < std::vector < T > > & ret, std::vector < T > & current, size_t depth ); - public: /** * @param re rte to probe * @param symbol FormalRTESymbol for which we need the follow(), i.e., Follow(RTE, symbol) + * @param substMapTree Tree substitution mapping from, rte::GlushkovSubstitutionMap::substMap * @return all symbols that can follow specific symbol in word */ template < class SymbolType, class RankType > - static std::set < TFollowTuple < SymbolType, RankType > > follow ( const rte::FormalRTE < SymbolType, RankType > & re, const std::ranked_symbol < SymbolType, RankType > & symbol ); + static std::set < TFollowTuple < SymbolType, RankType > > follow ( const rte::FormalRTE < SymbolType, RankType > & rte, const std::ranked_symbol < SymbolType, RankType > & symbol, const std::map < const rte::FormalRTEElement < SymbolType, RankType > *, TSubstMap < SymbolType, RankType > > & substMapTree ); template < class SymbolType, class RankType > class Formal { public: - static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEElement < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM ); - static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM ); - static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM ); - static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM ); - static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM ); - static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM ); - static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subM ); + static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEElement < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ); + static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ); + static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ); + static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ); + static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ); + static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ); + static std::set < TFollowTuple < SymbolType, RankType > > visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbol, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ); + }; }; template < class SymbolType, class RankType > -std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::follow ( const rte::FormalRTE < SymbolType, RankType > & rte, const std::ranked_symbol < SymbolType, RankType > & symbol ) { - TSubstMap < SymbolType, RankType > subMap; - - /* Init substitution map, ie \forall a \in K: sub[a] = \emptyset */ - for ( const std::ranked_symbol < SymbolType, RankType > & ssymb : rte.getSubstitutionAlphabet ( ) ) - subMap.insert ( std::make_pair ( ssymb, TAlphabet < SymbolType, RankType > { } ) ); - - /* recursively compute follow */ - return rte.getRTE ( ).getStructure ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbol, rte.getSubstitutionAlphabet ( ), subMap ); +std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::follow ( const rte::FormalRTE < SymbolType, RankType > & rte, const std::ranked_symbol < SymbolType, RankType > & symbol, const std::map < const rte::FormalRTEElement < SymbolType, RankType > *, TSubstMap < SymbolType, RankType > > & substMapTree ) { + return rte.getRTE ( ).getStructure ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbol, rte.getSubstitutionAlphabet ( ), substMapTree ); } // ----------------------------------------------------------------------------- -/** - * Preprocessing: - * - Let k1, k2 be elements of alphabet K. - * - If k1 is an element of substMap[k2], then copy content of substMap[k1] into substMap[k2] - */ template < class SymbolType, class RankType > -void GlushkovFollowV3::preprocessSubMap ( const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) { - for ( bool change = true; change; change = false ) - for ( std::pair < const std::ranked_symbol < SymbolType, RankType >, TAlphabet < SymbolType, RankType > > & kv : subMap ) { - TAlphabet < SymbolType, RankType > & substSet = kv.second; - - for ( auto eIter = substSet.begin ( ); eIter != substSet.end ( ); ) { - if ( alphabetK.count ( * eIter ) == 0 ) { - ++eIter; - } else { - auto it = subMap.find ( * eIter ); - size_t oldSize = substSet.size ( ); - substSet.insert ( it->second.begin ( ), it->second.end ( ) ); - change = ( oldSize != substSet.size ( ) ); // something was added - eIter = substSet.erase ( eIter ); - } - } - } -} +std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::replaceConstants ( const TAlphabet < SymbolType, RankType > & alphabetK, const std::vector < std::ranked_symbol < SymbolType, RankType > > & children, const TSubstMap < SymbolType, RankType > & subMap ) { + TFollowTuple < SymbolType, RankType > follow; -template < class SymbolType, class RankType > -std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::replaceConstants ( const TAlphabet < SymbolType, RankType > & alphabetK, const std::vector < std::ranked_symbol < SymbolType, RankType > > & follow, const TSubstMap < SymbolType, RankType > & subMap2 ) { - TSubstMap < SymbolType, RankType > subMap ( subMap2 ); - preprocessSubMap ( alphabetK, subMap ); - - TFollowTuple < SymbolType, RankType > children_follow; - - for ( const std::ranked_symbol < SymbolType, RankType > & e : follow ) { + for ( const std::ranked_symbol < SymbolType, RankType > & e : children ) { if ( alphabetK.count ( e ) > 0 ) - children_follow.push_back ( std::set < std::ranked_symbol < SymbolType, RankType > > ( subMap.at ( e ).begin ( ), subMap.at ( e ).end ( ) ) ); + follow.push_back ( std::set < std::ranked_symbol < SymbolType, RankType > > ( subMap.at ( e ).begin ( ), subMap.at ( e ).end ( ) ) ); else - children_follow.push_back ( std::set < std::ranked_symbol < SymbolType, RankType > > { e } ); + follow.push_back ( std::set < std::ranked_symbol < SymbolType, RankType > > { e } ); } - return { children_follow }; + return std::set < TFollowTuple < SymbolType, RankType > > { follow }; } // ----------------------------------------------------------------------------- template < class SymbolType, class RankType > -std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) { +std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ) { std::set < TFollowTuple < SymbolType, RankType > > ret, tmp; - tmp = node.getLeftElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap ); + tmp = node.getLeftElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree ); ret.insert ( tmp.begin ( ), tmp.end ( ) ); - tmp = node.getRightElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap ); + tmp = node.getRightElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree ); ret.insert ( tmp.begin ( ), tmp.end ( ) ); return ret; } template < class SymbolType, class RankType > -std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) { - - TSubstMap < SymbolType, RankType > subMapLeft ( subMap ); - auto itMap = subMapLeft.find ( node.getSubstitutionSymbol ( ).getSymbol ( ) ); - - itMap->second.clear ( ); - - for ( const auto & s : node.getRightElement ( ).template accept < TAlphabet < SymbolType, RankType >, GlushkovFirst::Formal < SymbolType, RankType > > ( ) ) - itMap->second.insert ( s ); - +std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ) { /* * E sub F * 1. if symbolF in F subtree, then Follow(F, symbolF); @@ -165,24 +114,18 @@ std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFol */ if ( node.getLeftElement ( ).template accept < bool, GlushkovPos::Formal < SymbolType, RankType > > ( symbolF ) ) - return node.getLeftElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMapLeft ); + return node.getLeftElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree ); else - return node.getRightElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap ); + return node.getRightElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree ); } template < class SymbolType, class RankType > -std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) { - - std::set < TFollowTuple < SymbolType, RankType > > ret; - - for ( const auto & s : node.getElement ( ).template accept < TAlphabet < SymbolType, RankType >, GlushkovFirst::Formal < SymbolType, RankType > > ( ) ) - subMap[node.getSubstitutionSymbol ( ).getSymbol ( )].insert ( s ); - - return node.getElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap ); +std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ) { + return node.getElement ( ).template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree ); } template < class SymbolType, class RankType > -std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, TSubstMap < SymbolType, RankType > & subMap ) { +std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, const std::ranked_symbol < SymbolType, RankType > & symbolF, const TAlphabet < SymbolType, RankType > & alphabetK, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & substMapTree ) { std::set < TFollowTuple < SymbolType, RankType > > ret, tmp; @@ -192,11 +135,11 @@ std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFol for ( const std::smart_ptr < const rte::FormalRTESymbol < SymbolType, RankType > > & c : node.getElements ( ) ) children.push_back ( c->getSymbol ( ) ); - return replaceConstants ( alphabetK, children, subMap ); + return replaceConstants ( alphabetK, children, substMapTree.at( & node )); } for ( const auto & c : node.getElements ( ) ) { - tmp = c->template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, subMap ); + tmp = c->template accept < std::set < TFollowTuple < SymbolType, RankType > >, GlushkovFollowV3::Formal < SymbolType, RankType > > ( symbolF, alphabetK, substMapTree ); ret.insert ( tmp.begin ( ), tmp.end ( ) ); } @@ -204,12 +147,12 @@ std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFol } template < class SymbolType, class RankType > -std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & /* node */, const std::ranked_symbol < SymbolType, RankType > & /* symbolF */, const TAlphabet < SymbolType, RankType > & /* alphabetK */, TSubstMap < SymbolType, RankType > & /* subMap */ ) { +std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & /* node */, const std::ranked_symbol < SymbolType, RankType > & /* symbol */, const TAlphabet < SymbolType, RankType > & /* alphabetK */, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & /* substMapTree */ ) { return std::set < TFollowTuple < SymbolType, RankType > > ( ); } template < class SymbolType, class RankType > -std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & /* node */, const std::ranked_symbol < SymbolType, RankType > & /* symbolF */, const TAlphabet < SymbolType, RankType > & /* alphabetK */, TSubstMap < SymbolType, RankType > & /* subMap */ ) { +std::set < GlushkovFollowV3::TFollowTuple < SymbolType, RankType > > GlushkovFollowV3::Formal < SymbolType, RankType > ::visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & /* node */, const std::ranked_symbol < SymbolType, RankType > & /* symbol */, const TAlphabet < SymbolType, RankType > & /* alphabetK */, const std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > & /* substMapTree */ ) { return std::set < TFollowTuple < SymbolType, RankType > > ( ); } diff --git a/alib2algo/src/rte/glushkov/GlushkovSubstitutionMap.h b/alib2algo/src/rte/glushkov/GlushkovSubstitutionMap.h new file mode 100644 index 0000000000..703d279a18 --- /dev/null +++ b/alib2algo/src/rte/glushkov/GlushkovSubstitutionMap.h @@ -0,0 +1,176 @@ +/* + * GlushkovSubstitutionMap.h + * + * Created on: 26. 7. 2017 + * Author: Tomas Pecka + */ + +#ifndef RTE_GLUSHKOV_SUBSTITUTION_MAP_H_ +#define RTE_GLUSHKOV_SUBSTITUTION_MAP_H_ + +#include <map> +#include <set> +#include <vector> + +#include <rte/formal/FormalRTE.h> +#include <rte/formal/FormalRTEElements.h> + +#include <alphabet/RankedSymbol.h> + +#include "GlushkovFirst.h" +#include "GlushkovPos.h" +#include <iterator> +#include <vector> + +namespace rte { + +class GlushkovSubstitutionMap { + +private: + template < class SymbolType, class RankType > + using TSubstMap = std::map < std::ranked_symbol < SymbolType, RankType >, std::set < std::ranked_symbol < SymbolType, RankType > > >; + + template < class SymbolType, class RankType > + using TSubstMapTree = std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > >; + + template < class SymbolType, class RankType > + using TAlphabet = std::set < std::ranked_symbol < SymbolType, RankType > >; + + // -------------------------------------------------------------------- + + template < class SymbolType, class RankType > + static void preprocessSubMap ( TSubstMap < SymbolType, RankType > & subMap, const TAlphabet < SymbolType, RankType > & alphabetK ); + + template < class SymbolType, class RankType > + static void subst_symbol_replaces ( std::map < const rte::FormalRTEElement < SymbolType, RankType > *, TSubstMap < SymbolType, RankType > > & substMapTree, const TAlphabet < SymbolType, RankType > & alphabetK ); + +public: + /** + * @param re rte to probe + * @return subst map for all RTE syntax tree elements + */ + template < class SymbolType, class RankType > + static std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > substMap ( const rte::FormalRTE < SymbolType, RankType > & re ); + + template < class SymbolType, class RankType > + class Formal { + public: + static void visit ( const rte::FormalRTEElement < SymbolType, RankType > & node, TSubstMap < SymbolType, RankType > & subM, TSubstMapTree < SymbolType, RankType > & subMapTree ); + static void visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, TSubstMap < SymbolType, RankType > & subM, TSubstMapTree < SymbolType, RankType > & subMapTree ); + static void visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, TSubstMap < SymbolType, RankType > & subM, TSubstMapTree < SymbolType, RankType > & subMapTree ); + static void visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, TSubstMap < SymbolType, RankType > & subM, TSubstMapTree < SymbolType, RankType > & subMapTree ); + static void visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, TSubstMap < SymbolType, RankType > & subM, TSubstMapTree < SymbolType, RankType > & subMapTree ); + static void visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & node, TSubstMap < SymbolType, RankType > & subM, TSubstMapTree < SymbolType, RankType > & subMapTree ); + static void visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & node, TSubstMap < SymbolType, RankType > & subM, TSubstMapTree < SymbolType, RankType > & subMapTree ); + }; + +}; + +// ----------------------------------------------------------------------------- + +template < class SymbolType, class RankType > +void GlushkovSubstitutionMap::subst_symbol_replaces ( std::map < const rte::FormalRTEElement < SymbolType, RankType > *, TSubstMap < SymbolType, RankType > > & substMapTree, const TAlphabet < SymbolType, RankType > & alphabetK ) { + for ( std::pair < const rte::FormalRTEElement < SymbolType, RankType > * const, TSubstMap < SymbolType, RankType > > & kv : substMapTree ) { + preprocessSubMap ( kv.second, alphabetK ); + } +} + +/** + * Preprocessing: + * - Let k1, k2 be elements of alphabet K. + * - If k1 is an element of substMap[k2], then copy content of substMap[k1] into substMap[k2] + */ +template < class SymbolType, class RankType > +void GlushkovSubstitutionMap::preprocessSubMap ( TSubstMap < SymbolType, RankType > & subMap, const TAlphabet < SymbolType, RankType > & alphabetK ) { + for ( bool change = true; change; change = false ) + for ( std::pair < const std::ranked_symbol < SymbolType, RankType >, TAlphabet < SymbolType, RankType > > & kv : subMap ) { + TAlphabet < SymbolType, RankType > & substSet = kv.second; + + for ( auto eIter = substSet.begin ( ); eIter != substSet.end ( ); ) { + if ( alphabetK.count ( * eIter ) == 0 ) { + ++eIter; + } else { + auto it = subMap.find ( * eIter ); + size_t oldSize = substSet.size ( ); + substSet.insert ( it->second.begin ( ), it->second.end ( ) ); + change = ( oldSize != substSet.size ( ) ); // something was added + eIter = substSet.erase ( eIter ); + } + } + } +} + +// ----------------------------------------------------------------------------- + +template < class SymbolType, class RankType > +std::map < const rte::FormalRTEElement < SymbolType, RankType >*, GlushkovSubstitutionMap::TSubstMap < SymbolType, RankType > > GlushkovSubstitutionMap::substMap ( const rte::FormalRTE < SymbolType, RankType > & rte ) { + TSubstMap < SymbolType, RankType > subMap; + std::map < const rte::FormalRTEElement < SymbolType, RankType >*, TSubstMap < SymbolType, RankType > > subMapTree; + + /* Init substitution map, ie \forall a \in K: sub[a] = \emptyset */ + for ( const std::ranked_symbol < SymbolType, RankType > & ssymb : rte.getSubstitutionAlphabet ( ) ) + subMap.insert ( std::make_pair ( ssymb, TAlphabet < SymbolType, RankType > { } ) ); + + /* recursively compute substMap */ + rte.getRTE ( ).getStructure ( ).template accept < void, GlushkovSubstitutionMap::Formal < SymbolType, RankType > > ( subMap, subMapTree ); + subst_symbol_replaces ( subMapTree, rte.getSubstitutionAlphabet ( ) ); + return subMapTree; +} + +// ----------------------------------------------------------------------------- + +template < class SymbolType, class RankType > +void GlushkovSubstitutionMap::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, TSubstMap < SymbolType, RankType > & subMap, TSubstMapTree < SymbolType, RankType > & subMapTree ) { + subMapTree.insert ( std::make_pair ( & node, subMap ) ); + node.getLeftElement ( ).template accept < void, GlushkovSubstitutionMap::Formal < SymbolType, RankType > > ( subMap, subMapTree ); + node.getRightElement ( ).template accept < void, GlushkovSubstitutionMap::Formal < SymbolType, RankType > > ( subMap, subMapTree ); +} + +template < class SymbolType, class RankType > +void GlushkovSubstitutionMap::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, TSubstMap < SymbolType, RankType > & subMap, TSubstMapTree < SymbolType, RankType > & subMapTree ) { + subMapTree.insert ( std::make_pair ( & node, subMap ) ); + + // re-init left map + TSubstMap < SymbolType, RankType > subMapLeft ( subMap ); + auto itMap = subMapLeft.find ( node.getSubstitutionSymbol ( ).getSymbol ( ) ); + itMap->second.clear ( ); + + for ( const auto & s : node.getRightElement ( ).template accept < std::set < std::ranked_symbol < > >, GlushkovFirst::Formal < SymbolType, RankType > > ( ) ) + itMap->second.insert ( s ); + + node.getLeftElement ( ).template accept < void, GlushkovSubstitutionMap::Formal < SymbolType, RankType > > ( subMapLeft, subMapTree ); + node.getRightElement ( ).template accept < void, GlushkovSubstitutionMap::Formal < SymbolType, RankType > > ( subMap, subMapTree ); +} + +template < class SymbolType, class RankType > +void GlushkovSubstitutionMap::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, TSubstMap < SymbolType, RankType > & subMap, TSubstMapTree < SymbolType, RankType > & subMapTree ) { + subMapTree.insert ( std::make_pair ( & node, subMap ) ); + + for ( const auto & s : node.getElement ( ).template accept < TAlphabet < SymbolType, RankType >, GlushkovFirst::Formal < SymbolType, RankType > > ( ) ) + subMap[node.getSubstitutionSymbol ( ).getSymbol ( )].insert ( s ); + + node.getElement ( ).template accept < void, GlushkovSubstitutionMap::Formal < SymbolType, RankType > > ( subMap, subMapTree ); +} + +template < class SymbolType, class RankType > +void GlushkovSubstitutionMap::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, TSubstMap < SymbolType, RankType > & subMap, TSubstMapTree < SymbolType, RankType > & subMapTree ) { + subMapTree.insert ( std::make_pair ( & node, subMap ) ); + + for ( const auto & c : node.getElements ( ) ) { + c -> template accept < void, GlushkovSubstitutionMap::Formal < SymbolType, RankType > > ( subMap, subMapTree ); + } +} + +template < class SymbolType, class RankType > +void GlushkovSubstitutionMap::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & node, TSubstMap < SymbolType, RankType > & subMap, TSubstMapTree < SymbolType, RankType > & subMapTree ) { + subMapTree.insert ( std::make_pair ( & node, subMap ) ); +} + +template < class SymbolType, class RankType > +void GlushkovSubstitutionMap::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & node, TSubstMap < SymbolType, RankType > & subMap, TSubstMapTree < SymbolType, RankType > & subMapTree ) { + subMapTree.insert ( std::make_pair ( & node, subMap ) ); +} + +} /* namespace rte */ + +#endif /* RTE_GLUSHKOV_SUBSTITUTION_MAP_H_ */ -- GitLab