diff --git a/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp b/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp index 76c1ae8dc497732a349cc1e63298ff322c0dea37..bc75619a6bafa0ca86315695596fad4fdb0d9e02 100644 --- a/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp +++ b/alib2algo/src/grammar/generate/CockeYoungerKasami.cpp @@ -6,76 +6,11 @@ */ #include "CockeYoungerKasami.h" -#include <global/GlobalData.h> namespace grammar { namespace generate { -bool CockeYoungerKasami::generate ( const grammar::CNF < > & grammar, const string::LinearString < > & string ) { - unsigned stringSize = string.getContent ( ).size ( ); - - if ( ( stringSize == 0 ) && grammar.getGeneratesEpsilon ( ) ) return true; - - std::vector < std::vector < std::set < alphabet::Symbol > > > data; - data.resize ( stringSize ); - - for ( unsigned i = 0; i < stringSize; i++ ) - data[i].resize ( stringSize - i ); - - for ( unsigned i = 0; i < stringSize; i++ ) - for ( const std::pair < const alphabet::Symbol, std::set < std::variant < alphabet::Symbol, std::pair < alphabet::Symbol, alphabet::Symbol > > > > rule : grammar.getRules ( ) ) { - const alphabet::Symbol & lhs = rule.first; - - for ( const std::variant < alphabet::Symbol, std::pair < alphabet::Symbol, alphabet::Symbol > > rhs : rule.second ) - if ( rhs.is < alphabet::Symbol > ( ) && ( rhs.get < alphabet::Symbol > ( ) == string.getContent ( )[i] ) ) - data[0][i].insert ( lhs ); - - } - - - - for ( unsigned i = 1; i < stringSize; i++ ) - for ( unsigned j = 0; j < stringSize - i; j++ ) { - std::set < alphabet::Symbol > & targetCell = data[i][j]; // Element to compute - - for ( unsigned k = 0; k < i; k++ ) { - const std::set < alphabet::Symbol > & vertical = data[k][j]; - const std::set < alphabet::Symbol > & diagonal = data[i - 1 - k][j + 1 + k]; // Sources of data - - for ( const alphabet::Symbol & verticalElement : vertical ) { - for ( const alphabet::Symbol & diagonalElement : diagonal ) - - for ( const std::pair < const alphabet::Symbol, std::set < std::variant < alphabet::Symbol, std::pair < alphabet::Symbol, alphabet::Symbol > > > > rule : grammar.getRules ( ) ) { - const alphabet::Symbol & lhs = rule.first; - - for ( const std::variant < alphabet::Symbol, std::pair < alphabet::Symbol, alphabet::Symbol > > rhs : rule.second ) - if ( rhs.is < std::pair < alphabet::Symbol, alphabet::Symbol > > ( ) ) { - const std::pair < alphabet::Symbol, alphabet::Symbol > rhsp = rhs.get < std::pair < alphabet::Symbol, alphabet::Symbol > > ( ); - - if ( ( rhsp.first == verticalElement ) && ( rhsp.second == diagonalElement ) ) - targetCell.insert ( lhs ); - } - - } - - } - } - } - - - - if ( common::GlobalData::verbose ) - for ( const std::vector < std::set < alphabet::Symbol > > & row : data ) { - for ( const std::set < alphabet::Symbol > & element : row ) - std::clog << element << " "; - - std::clog << std::endl; - } - - return data[stringSize - 1][0].count ( grammar.getInitialSymbol ( ) ); -} - auto CockeYoungerKasamiCNF = CockeYoungerKasami::RegistratorWrapper < bool, grammar::CNF < > > ( CockeYoungerKasami::generate ); bool CockeYoungerKasami::generate ( const grammar::Grammar & grammar, const string::LinearString < > & string ) { diff --git a/alib2algo/src/grammar/generate/CockeYoungerKasami.h b/alib2algo/src/grammar/generate/CockeYoungerKasami.h index 8926099d0a2f2e131247072f3331d8668992b295..e811bb99e2441a746cb7e7b374c9ccda280123ff 100644 --- a/alib2algo/src/grammar/generate/CockeYoungerKasami.h +++ b/alib2algo/src/grammar/generate/CockeYoungerKasami.h @@ -9,6 +9,7 @@ #define COCKE_YOUNGER_KASAMI_H_ #include <core/multipleDispatch.hpp> +#include <global/GlobalData.h> #include <grammar/Grammar.h> #include <grammar/ContextFree/CNF.h> @@ -25,10 +26,74 @@ class CockeYoungerKasami : public std::SingleDispatch < CockeYoungerKasami, bool public: static bool generate ( const grammar::Grammar & grammar, const string::LinearString < > & string ); - static bool generate ( const grammar::CNF < > & grammar, const string::LinearString < > & string ); + template < class SymbolType > + static bool generate ( const grammar::CNF < SymbolType > & grammar, const string::LinearString < SymbolType > & string ); }; +template < class SymbolType > +bool CockeYoungerKasami::generate ( const grammar::CNF < SymbolType > & grammar, const string::LinearString < SymbolType > & string ) { + unsigned stringSize = string.getContent ( ).size ( ); + + if ( ( stringSize == 0 ) && grammar.getGeneratesEpsilon ( ) ) return true; + + std::vector < std::vector < std::set < SymbolType > > > data; + data.resize ( stringSize ); + + for ( unsigned i = 0; i < stringSize; i++ ) + data[i].resize ( stringSize - i ); + + for ( unsigned i = 0; i < stringSize; i++ ) + for ( const std::pair < const SymbolType, std::set < std::variant < SymbolType, std::pair < SymbolType, SymbolType > > > > rule : grammar.getRules ( ) ) { + const SymbolType & lhs = rule.first; + + for ( const std::variant < SymbolType, std::pair < SymbolType, SymbolType > > rhs : rule.second ) + if ( rhs.template is < SymbolType > ( ) && ( rhs.template get < SymbolType > ( ) == string.getContent ( )[i] ) ) + data[0][i].insert ( lhs ); + + } + + for ( unsigned i = 1; i < stringSize; i++ ) + for ( unsigned j = 0; j < stringSize - i; j++ ) { + std::set < SymbolType > & targetCell = data[i][j]; // Element to compute + + for ( unsigned k = 0; k < i; k++ ) { + const std::set < SymbolType > & vertical = data[k][j]; + const std::set < SymbolType > & diagonal = data[i - 1 - k][j + 1 + k]; // Sources of data + + for ( const SymbolType & verticalElement : vertical ) { + for ( const SymbolType & diagonalElement : diagonal ) + + for ( const std::pair < const SymbolType, std::set < std::variant < SymbolType, std::pair < SymbolType, SymbolType > > > > rule : grammar.getRules ( ) ) { + const SymbolType & lhs = rule.first; + + for ( const std::variant < SymbolType, std::pair < SymbolType, SymbolType > > rhs : rule.second ) + if ( rhs.template is < std::pair < SymbolType, SymbolType > > ( ) ) { + const std::pair < SymbolType, SymbolType > rhsp = rhs.template get < std::pair < SymbolType, SymbolType > > ( ); + + if ( ( rhsp.first == verticalElement ) && ( rhsp.second == diagonalElement ) ) + targetCell.insert ( lhs ); + } + + } + + } + } + } + + + + if ( common::GlobalData::verbose ) + for ( const std::vector < std::set < SymbolType > > & row : data ) { + for ( const std::set < SymbolType > & element : row ) + std::clog << element << " "; + + std::clog << std::endl; + } + + return data[stringSize - 1][0].count ( grammar.getInitialSymbol ( ) ); +} + } /* namespace generate */ } /* namespace grammar */ diff --git a/alib2algo/src/grammar/generate/GenerateUpToLength.cpp b/alib2algo/src/grammar/generate/GenerateUpToLength.cpp index 3a9a881c68160593ca71c2ab1fbfb678aa9c39f9..4ad8f0f544d49e80fd637833c26105a814eef961 100644 --- a/alib2algo/src/grammar/generate/GenerateUpToLength.cpp +++ b/alib2algo/src/grammar/generate/GenerateUpToLength.cpp @@ -7,60 +7,10 @@ #include "GenerateUpToLength.h" -#include <grammar/ContextFree/EpsilonFreeCFG.h> -#include <grammar/ContextFree/GNF.h> -#include <grammar/ContextFree/CNF.h> -#include <grammar/Regular/LeftRG.h> -#include <grammar/Regular/RightRG.h> - -#include <deque> - namespace grammar { namespace generate { -template<class T> -std::set<string::LinearString < >> GenerateUpToLength::generate( const T & grammar, unsigned length ) { - std::set<string::LinearString < >> res; - - std::map<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>> rules = grammar.getRawRules(); - if(grammar.getGeneratesEpsilon()) { - res.insert(string::LinearString < > {}); - rules[grammar.getInitialSymbol()].erase(std::vector<alphabet::Symbol> {}); - } - - std::deque<std::pair<std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol>>> data; - data.push_back(std::make_pair(std::vector<alphabet::Symbol>{}, std::vector<alphabet::Symbol>{grammar.getInitialSymbol()})); - while(!data.empty()) { - std::pair<std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol>> item = std::move(data.back()); - data.pop_back(); - - alphabet::Symbol nonterminal = std::move(item.second.back()); - item.second.pop_back(); - if(rules.find(nonterminal) == rules.end()) continue; - - for(const std::vector<alphabet::Symbol>& rhs : rules.find(nonterminal)->second) { - if(item.first.size() + item.second.size() + rhs.size() > length) continue; - - std::vector<alphabet::Symbol> newStack(item.second); - std::vector<alphabet::Symbol> newString(item.first); - newStack.insert(newStack.end(), rhs.rbegin(), rhs.rend()); - - while(!newStack.empty() && grammar.getTerminalAlphabet().count(newStack.back())) { - newString.push_back(std::move(newStack.back())); - newStack.pop_back(); - } - - if(newStack.empty()) { - res.insert(string::LinearString < >(newString)); - } else { - data.push_back(std::make_pair(std::move(newString), std::move(newStack))); - } - } - } - return res; -} - auto GenerateUpToLengthEpsilonFreeCFG = GenerateUpToLength::RegistratorWrapper<std::set<string::LinearString < >>, grammar::EpsilonFreeCFG < > >(GenerateUpToLength::generate); auto GenerateUpToLengthGNF = GenerateUpToLength::RegistratorWrapper<std::set<string::LinearString < >>, grammar::GNF < > >(GenerateUpToLength::generate); auto GenerateUpToLengthCNF = GenerateUpToLength::RegistratorWrapper<std::set<string::LinearString < >>, grammar::CNF < > >(GenerateUpToLength::generate); diff --git a/alib2algo/src/grammar/generate/GenerateUpToLength.h b/alib2algo/src/grammar/generate/GenerateUpToLength.h index 4fd0ddd8bbd9784b1c28b3aa8ac19752faee358b..30e457abc22d4db3725c4060273511cf8e81aa3b 100644 --- a/alib2algo/src/grammar/generate/GenerateUpToLength.h +++ b/alib2algo/src/grammar/generate/GenerateUpToLength.h @@ -13,6 +13,13 @@ #include <grammar/Grammar.h> #include <string/LinearString.h> #include <set> +#include <deque> + +#include <grammar/ContextFree/EpsilonFreeCFG.h> +#include <grammar/ContextFree/GNF.h> +#include <grammar/ContextFree/CNF.h> +#include <grammar/Regular/LeftRG.h> +#include <grammar/Regular/RightRG.h> namespace grammar { @@ -21,14 +28,58 @@ namespace generate { /** * Implements algorithms from Melichar, chapter 3.3 */ -class GenerateUpToLength : public std::SingleDispatch<GenerateUpToLength, std::set < string::LinearString < > >, const grammar::GrammarBase &, unsigned> { +class GenerateUpToLength : public std::SingleDispatch < GenerateUpToLength, std::set < string::LinearString < > >, const grammar::GrammarBase &, unsigned > { public: - static std::set<string::LinearString < >> generate( const grammar::Grammar & grammar, unsigned length ); + static std::set < string::LinearString < > > generate( const grammar::Grammar & grammar, unsigned length ); - template<class T> - static std::set<string::LinearString < >> generate( const T & grammar, unsigned length ); + template < class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > > + static std::set < string::LinearString < SymbolType > > generate ( const T & grammar, unsigned length ); }; +template < class T, class SymbolType > +std::set < string::LinearString < SymbolType > > GenerateUpToLength::generate ( const T & grammar, unsigned length ) { + std::set < string::LinearString < SymbolType > > res; + + std::map < SymbolType, std::set < std::vector < SymbolType > > > rules = grammar.getRawRules(); + if ( grammar.getGeneratesEpsilon ( ) ) { + res.insert ( string::LinearString < SymbolType > { } ); + rules [ grammar.getInitialSymbol ( ) ].erase ( std::vector < SymbolType > { } ); + } + + std::deque < std::pair < std::vector < SymbolType >, std::vector < SymbolType > > > data; + data.push_back ( std::make_pair ( std::vector < SymbolType > { }, std::vector < SymbolType > { grammar.getInitialSymbol ( ) } ) ); + + while ( ! data.empty ( ) ) { + std::pair < std::vector < SymbolType >, std::vector < SymbolType > > item = std::move ( data.back ( ) ); + data.pop_back ( ); + + SymbolType nonterminal = std::move ( item.second.back ( ) ); + item.second.pop_back ( ); + if ( rules.find ( nonterminal ) == rules.end ( ) ) continue; + + for ( const std::vector < SymbolType > & rhs : rules.find ( nonterminal )->second ) { + if ( item.first.size ( ) + item.second.size ( ) + rhs.size ( ) > length ) continue; + + std::vector < SymbolType > newStack ( item.second ); + std::vector < SymbolType > newString ( item.first ); + newStack.insert ( newStack.end ( ), rhs.rbegin ( ), rhs.rend ( ) ); + + while ( ! newStack.empty ( ) && grammar.getTerminalAlphabet ( ).count ( newStack.back ( ) ) ) { + newString.push_back ( std::move(newStack.back ( ) ) ); + newStack.pop_back ( ); + } + + if ( newStack.empty ( ) ) { + res.insert ( string::LinearString < SymbolType > ( newString ) ); + } else { + data.push_back ( std::make_pair ( std::move ( newString ), std::move ( newStack ) ) ); + } + } + } + + return res; +} + } /* namespace generate */ } /* namespace grammar */ diff --git a/alib2algo/src/grammar/simplify/SimpleRulesRemover.cpp b/alib2algo/src/grammar/simplify/SimpleRulesRemover.cpp index 51e2b43bcfdfe1becdfba4c281d6478d75d63380..dad3a970c9a9914c19977981ac68ee04f9d2698d 100644 --- a/alib2algo/src/grammar/simplify/SimpleRulesRemover.cpp +++ b/alib2algo/src/grammar/simplify/SimpleRulesRemover.cpp @@ -7,124 +7,24 @@ #include "SimpleRulesRemover.h" -#include "../properties/NonterminalUnitRuleCycle.h" - namespace grammar { namespace simplify { -template<class T> -T removeEpsilonFree( const T & origGrammar ) { - T grammar(origGrammar.getInitialSymbol()); - - for( const auto & symbol : origGrammar.getNonterminalAlphabet() ) - grammar.addNonterminalSymbol( symbol ); - - for( const auto & symbol : origGrammar.getTerminalAlphabet() ) - grammar.addTerminalSymbol( symbol ); - - auto origRules = origGrammar.getRawRules(); - - for( const auto & symbol : origGrammar.getNonterminalAlphabet() ) { - std::set<alphabet::Symbol> simpleRulesClosure = grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(origGrammar, symbol); - for( const auto & closureSymbol : simpleRulesClosure ) { - auto rules = origRules.find(closureSymbol); - if(rules != origRules.end()) for( const auto& rawRule : rules->second ) { - if(rawRule.size() == 0 || (rawRule.size() == 1 && !origGrammar.getNonterminalAlphabet().count(rawRule[0])) || rawRule.size() >= 2) - grammar.addRawRule(symbol, rawRule); - } - } - } - - grammar.setGeneratesEpsilon(origGrammar.getGeneratesEpsilon()); - - return grammar; -} - -template<class T> -T removeNonEpsilonFree( const T & origGrammar ) { - T grammar(origGrammar.getInitialSymbol()); - - for( const auto & symbol : origGrammar.getNonterminalAlphabet() ) - grammar.addNonterminalSymbol( symbol ); - - for( const auto & symbol : origGrammar.getTerminalAlphabet() ) - grammar.addTerminalSymbol( symbol ); - - auto origRules = origGrammar.getRawRules(); - - for( const auto & symbol : origGrammar.getNonterminalAlphabet() ) { - std::set<alphabet::Symbol> simpleRulesClosure = grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(origGrammar, symbol); - for( const auto & closureSymbol : simpleRulesClosure ) { - auto rules = origRules.find(closureSymbol); - if(rules != origRules.end()) for( const auto& rawRule : rules->second ) { - if(rawRule.size() == 0 || (rawRule.size() == 1 && !origGrammar.getNonterminalAlphabet().count(rawRule[0])) || rawRule.size() >= 2) - grammar.addRawRule(symbol, rawRule); - } - } - } - - return grammar; -} - -grammar::CFG < > SimpleRulesRemover::remove(const grammar::CFG < > & origGrammar) { - return removeNonEpsilonFree(origGrammar); +grammar::Grammar SimpleRulesRemover::remove ( const grammar::Grammar & grammar ) { + return dispatch ( grammar.getData ( ) ); } auto SimpleRulesRemoverCFG = SimpleRulesRemover::RegistratorWrapper<grammar::CFG < >, grammar::CFG < > >(SimpleRulesRemover::remove); - -grammar::EpsilonFreeCFG < > SimpleRulesRemover::remove(const grammar::EpsilonFreeCFG < > & origGrammar) { - return removeEpsilonFree(origGrammar); -} - auto SimpleRulesRemoverEpsilonFreeCFG = SimpleRulesRemover::RegistratorWrapper<grammar::EpsilonFreeCFG < >, grammar::EpsilonFreeCFG < > >(SimpleRulesRemover::remove); - -grammar::CNF < > SimpleRulesRemover::remove(const grammar::CNF < > & origGrammar) { - return origGrammar; -} - auto SimpleRulesRemoverCNF = SimpleRulesRemover::RegistratorWrapper<grammar::CNF < >, grammar::CNF < > >(SimpleRulesRemover::remove); - -grammar::GNF < > SimpleRulesRemover::remove(const grammar::GNF < > & origGrammar) { - return origGrammar; -} - auto SimpleRulesRemoverGNF = SimpleRulesRemover::RegistratorWrapper<grammar::GNF < >, grammar::GNF < > >(SimpleRulesRemover::remove); - -grammar::LG < > SimpleRulesRemover::remove(const grammar::LG < > & origGrammar) { - return removeNonEpsilonFree(origGrammar); -} - auto SimpleRulesRemoverLG = SimpleRulesRemover::RegistratorWrapper<grammar::LG < >, grammar::LG < > >(SimpleRulesRemover::remove); - -grammar::LeftLG < > SimpleRulesRemover::remove(const grammar::LeftLG < > & origGrammar) { - return removeNonEpsilonFree(origGrammar); -} - auto SimpleRulesRemoverLeftLG = SimpleRulesRemover::RegistratorWrapper<grammar::LeftLG < >, grammar::LeftLG < > >(SimpleRulesRemover::remove); - -grammar::LeftRG < > SimpleRulesRemover::remove(const grammar::LeftRG < > & origGrammar) { - return origGrammar; -} - auto SimpleRulesRemoverLeftRG = SimpleRulesRemover::RegistratorWrapper<grammar::LeftRG < >, grammar::LeftRG < > >(SimpleRulesRemover::remove); - -grammar::RightLG < > SimpleRulesRemover::remove(const grammar::RightLG < > & origGrammar) { - return removeNonEpsilonFree(origGrammar); -} - auto SimpleRulesRemoverRightLG = SimpleRulesRemover::RegistratorWrapper<grammar::RightLG < >, grammar::RightLG < > >(SimpleRulesRemover::remove); - -grammar::RightRG < > SimpleRulesRemover::remove(const grammar::RightRG < > & origGrammar) { - return origGrammar; -} - auto SimpleRulesRemoverRightRG = SimpleRulesRemover::RegistratorWrapper<grammar::RightRG < >, grammar::RightRG < > >(SimpleRulesRemover::remove); -grammar::Grammar SimpleRulesRemover::remove(const grammar::Grammar& grammar) { - return dispatch(grammar.getData()); -} - } /* namespace simplify */ } /* namespace grammar */ diff --git a/alib2algo/src/grammar/simplify/SimpleRulesRemover.h b/alib2algo/src/grammar/simplify/SimpleRulesRemover.h index 75ee9dd457fb4f93a19a1e5af18b1ef8afa170db..1f5be634ef72d8d949a07c6b2356d077c8fa351e 100644 --- a/alib2algo/src/grammar/simplify/SimpleRulesRemover.h +++ b/alib2algo/src/grammar/simplify/SimpleRulesRemover.h @@ -24,25 +24,141 @@ #include <grammar/Regular/RightLG.h> #include <grammar/Regular/RightRG.h> +#include <grammar/properties/NonterminalUnitRuleCycle.h> + namespace grammar { namespace simplify { class SimpleRulesRemover : public std::SingleDispatch<SimpleRulesRemover, grammar::Grammar, const grammar::GrammarBase &> { + template<class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > > + static T removeEpsilonFree( const T & origGrammar ); + + template<class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > > + static T removeNonEpsilonFree( const T & origGrammar ); + public: static grammar::Grammar remove( const grammar::Grammar & grammar ); - static grammar::CFG < > remove( const grammar::CFG < > & grammar ); - static grammar::EpsilonFreeCFG < > remove( const grammar::EpsilonFreeCFG < > & grammar ); - static grammar::GNF < > remove( const grammar::GNF < > & grammar ); - static grammar::CNF < > remove( const grammar::CNF < > & grammar ); - static grammar::LG < > remove( const grammar::LG < > & grammar ); - static grammar::LeftLG < > remove( const grammar::LeftLG < > & grammar ); - static grammar::LeftRG < > remove( const grammar::LeftRG < > & grammar ); - static grammar::RightLG < > remove( const grammar::RightLG < > & grammar ); - static grammar::RightRG < > remove( const grammar::RightRG < > & grammar ); + template < class SymbolType > + static grammar::CFG < SymbolType > remove( const grammar::CFG < SymbolType > & grammar ); + template < class SymbolType > + static grammar::EpsilonFreeCFG < SymbolType > remove( const grammar::EpsilonFreeCFG < SymbolType > & grammar ); + template < class SymbolType > + static grammar::GNF < SymbolType > remove( const grammar::GNF < SymbolType > & grammar ); + template < class SymbolType > + static grammar::CNF < SymbolType > remove( const grammar::CNF < SymbolType > & grammar ); + template < class SymbolType > + static grammar::LG < SymbolType > remove( const grammar::LG < SymbolType > & grammar ); + template < class SymbolType > + static grammar::LeftLG < SymbolType > remove( const grammar::LeftLG < SymbolType > & grammar ); + template < class SymbolType > + static grammar::LeftRG < SymbolType > remove( const grammar::LeftRG < SymbolType > & grammar ); + template < class SymbolType > + static grammar::RightLG < SymbolType > remove( const grammar::RightLG < SymbolType > & grammar ); + template < class SymbolType > + static grammar::RightRG < SymbolType > remove( const grammar::RightRG < SymbolType > & grammar ); }; +template < class T, class SymbolType > +T SimpleRulesRemover::removeEpsilonFree( const T & origGrammar ) { + T grammar(origGrammar.getInitialSymbol()); + + for( const auto & symbol : origGrammar.getNonterminalAlphabet() ) + grammar.addNonterminalSymbol( symbol ); + + for( const auto & symbol : origGrammar.getTerminalAlphabet() ) + grammar.addTerminalSymbol( symbol ); + + auto origRules = origGrammar.getRawRules(); + + for( const auto & symbol : origGrammar.getNonterminalAlphabet() ) { + std::set<SymbolType> simpleRulesClosure = grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(origGrammar, symbol); + for( const auto & closureSymbol : simpleRulesClosure ) { + auto rules = origRules.find(closureSymbol); + if(rules != origRules.end()) for( const auto& rawRule : rules->second ) { + if(rawRule.size() == 0 || (rawRule.size() == 1 && !origGrammar.getNonterminalAlphabet().count(rawRule[0])) || rawRule.size() >= 2) + grammar.addRawRule(symbol, rawRule); + } + } + } + + grammar.setGeneratesEpsilon(origGrammar.getGeneratesEpsilon()); + + return grammar; +} + +template < class T, class SymbolType > +T SimpleRulesRemover::removeNonEpsilonFree( const T & origGrammar ) { + T grammar(origGrammar.getInitialSymbol()); + + for( const auto & symbol : origGrammar.getNonterminalAlphabet() ) + grammar.addNonterminalSymbol( symbol ); + + for( const auto & symbol : origGrammar.getTerminalAlphabet() ) + grammar.addTerminalSymbol( symbol ); + + auto origRules = origGrammar.getRawRules(); + + for( const auto & symbol : origGrammar.getNonterminalAlphabet() ) { + std::set<SymbolType> simpleRulesClosure = grammar::properties::NonterminalUnitRuleCycle::getNonterminalUnitRuleCycle(origGrammar, symbol); + for( const auto & closureSymbol : simpleRulesClosure ) { + auto rules = origRules.find(closureSymbol); + if(rules != origRules.end()) for( const auto& rawRule : rules->second ) { + if(rawRule.size() == 0 || (rawRule.size() == 1 && !origGrammar.getNonterminalAlphabet().count(rawRule[0])) || rawRule.size() >= 2) + grammar.addRawRule(symbol, rawRule); + } + } + } + + return grammar; +} + +template < class SymbolType > +grammar::CFG < SymbolType > SimpleRulesRemover::remove(const grammar::CFG < SymbolType > & origGrammar) { + return removeNonEpsilonFree(origGrammar); +} + +template < class SymbolType > +grammar::EpsilonFreeCFG < SymbolType > SimpleRulesRemover::remove(const grammar::EpsilonFreeCFG < SymbolType > & origGrammar) { + return removeEpsilonFree(origGrammar); +} + +template < class SymbolType > +grammar::CNF < SymbolType > SimpleRulesRemover::remove(const grammar::CNF < SymbolType > & origGrammar) { + return origGrammar; +} + +template < class SymbolType > +grammar::GNF < SymbolType > SimpleRulesRemover::remove(const grammar::GNF < SymbolType > & origGrammar) { + return origGrammar; +} + +template < class SymbolType > +grammar::LG < SymbolType > SimpleRulesRemover::remove(const grammar::LG < SymbolType > & origGrammar) { + return removeNonEpsilonFree(origGrammar); +} + +template < class SymbolType > +grammar::LeftLG < SymbolType > SimpleRulesRemover::remove(const grammar::LeftLG < SymbolType > & origGrammar) { + return removeNonEpsilonFree(origGrammar); +} + +template < class SymbolType > +grammar::LeftRG < SymbolType > SimpleRulesRemover::remove(const grammar::LeftRG < SymbolType > & origGrammar) { + return origGrammar; +} + +template < class SymbolType > +grammar::RightLG < SymbolType > SimpleRulesRemover::remove(const grammar::RightLG < SymbolType > & origGrammar) { + return removeNonEpsilonFree(origGrammar); +} + +template < class SymbolType > +grammar::RightRG < SymbolType > SimpleRulesRemover::remove(const grammar::RightRG < SymbolType > & origGrammar) { + return origGrammar; +} + } /* namespace simplify */ } /* namespace grammar */ diff --git a/alib2algo/src/grammar/simplify/ToGNF.cpp b/alib2algo/src/grammar/simplify/ToGNF.cpp index 9455f6f8be2cc856cd0486ec7d2ab20d32db6bb2..504937b475b71093c2ef957b239f3f49c7acb81b 100644 --- a/alib2algo/src/grammar/simplify/ToGNF.cpp +++ b/alib2algo/src/grammar/simplify/ToGNF.cpp @@ -7,138 +7,18 @@ #include "ToGNF.h" -#include "EpsilonRemover.h" -#include "SimpleRulesRemover.h" -#include "LeftRecursionRemover.h" -#include "../convert/ToGrammarRightRG.h" -#include "alphabet/SymbolPairSymbol.h" -#include <common/createUnique.hpp> - namespace grammar { namespace simplify { -grammar::EpsilonFreeCFG < > assignNonterminals(const grammar::EpsilonFreeCFG < > & origGrammar) { - grammar::EpsilonFreeCFG < > res(origGrammar.getInitialSymbol()); - res.setNonterminalAlphabet(origGrammar.getNonterminalAlphabet()); - res.setTerminalAlphabet(origGrammar.getTerminalAlphabet()); - res.setGeneratesEpsilon(origGrammar.getGeneratesEpsilon()); - - for(const std::pair<const alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>>& rule : origGrammar.getRules()) { - for(const std::vector<alphabet::Symbol>& singleRHS : rule.second) { - if(res.getTerminalAlphabet().count(singleRHS[0])) { //do not substitute terminals - res.addRule(rule.first, singleRHS); - continue; - } - const alphabet::Symbol& secondLHS = singleRHS[0]; - if(origGrammar.getRules().find(secondLHS) == origGrammar.getRules().end()) { //is there any right hand side to substitue with? - //if not well this rule does not generate anything anyway - continue; - } - - for(const std::vector<alphabet::Symbol>& secondSingleRHS : origGrammar.getRules().find(secondLHS)->second) { // do the substitution - std::vector<alphabet::Symbol> newRHS(secondSingleRHS); - newRHS.insert(newRHS.end(), singleRHS.begin() + 1, singleRHS.end()); - res.addRule(rule.first, newRHS); - } - } - } - return res; -} - -grammar::GNF < > convertInternal( const grammar::EpsilonFreeCFG < > & origGrammar ) { - grammar::EpsilonFreeCFG < > step(origGrammar); - while(true) { - grammar::EpsilonFreeCFG < > nextStep = assignNonterminals(step); - - if(step == nextStep) break; - step = std::move(nextStep); - } - - grammar::GNF < > res(step.getInitialSymbol()); - res.setTerminalAlphabet(step.getTerminalAlphabet()); - res.setNonterminalAlphabet(step.getNonterminalAlphabet()); - res.setGeneratesEpsilon(step.getGeneratesEpsilon()); - std::map<alphabet::Symbol, alphabet::Symbol> terminalToPrimed; - for(const alphabet::Symbol& terminal : step.getTerminalAlphabet()) { - alphabet::Symbol primed = common::createUnique(terminal, res.getTerminalAlphabet(), res.getNonterminalAlphabet()); - terminalToPrimed.insert(std::make_pair(terminal, primed)); - res.addNonterminalSymbol(primed); - res.addRule(primed, std::make_pair(terminal, std::vector<alphabet::Symbol> {})); - } - for(const auto& rule : step.getRules()) { - for(const auto& rhs : rule.second) { - std::vector<alphabet::Symbol> convertedNonterminals; - bool first = true; - for(const alphabet::Symbol& rhsSymbol : rhs) { - if(first) { - first = false; - continue; - } - - if(res.getNonterminalAlphabet().count(rhsSymbol)) - convertedNonterminals.push_back(rhsSymbol); - else - convertedNonterminals.push_back(terminalToPrimed.find(rhsSymbol)->second); - } - res.addRule(rule.first, std::make_pair(rhs[0], std::move(convertedNonterminals))); - } - } - return res; -} - -grammar::GNF < > ToGNF::convert(const grammar::CFG < > & origGrammar) { - return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar)))); -} - auto ToGNFCFG = ToGNF::RegistratorWrapper<grammar::GNF < >, grammar::CFG < > >(ToGNF::convert); - -grammar::GNF < > ToGNF::convert(const grammar::EpsilonFreeCFG < > & origGrammar) { - return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(origGrammar))); -} - auto ToGNFEpsilonFreeCFG = ToGNF::RegistratorWrapper<grammar::GNF < >, grammar::EpsilonFreeCFG < > >(ToGNF::convert); - -grammar::GNF < > ToGNF::convert(const grammar::CNF < > & origGrammar) { - return convertInternal(grammar::simplify::LeftRecursionRemover::remove(origGrammar)); -} - auto ToGNFCNF = ToGNF::RegistratorWrapper<grammar::GNF < >, grammar::CNF < > >(ToGNF::convert); - -grammar::GNF < > ToGNF::convert(const grammar::GNF < > & origGrammar) { - return origGrammar; -} - auto ToGNFGNF = ToGNF::RegistratorWrapper<grammar::GNF < >, grammar::GNF < > >(ToGNF::convert); - -grammar::GNF < > ToGNF::convert(const grammar::LG < > & origGrammar) { - return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar)))); -} - auto ToGNFLG = ToGNF::RegistratorWrapper<grammar::GNF < >, grammar::LG < > >(ToGNF::convert); - -grammar::GNF < > ToGNF::convert(const grammar::LeftLG < > & origGrammar) { - return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar)))); -} - auto ToGNFLeftLG = ToGNF::RegistratorWrapper<grammar::GNF < >, grammar::LeftLG < > >(ToGNF::convert); - -grammar::RightRG < > ToGNF::convert(const grammar::LeftRG < > & origGrammar) { - return convert::ToGrammarRightRG::convert(origGrammar); -} - auto ToGNFLeftRG = ToGNF::RegistratorWrapper<grammar::RightRG < >, grammar::LeftRG < > >(ToGNF::convert); - -grammar::GNF < > ToGNF::convert(const grammar::RightLG < > & origGrammar) { - return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar)))); -} - auto ToGNFRightLG = ToGNF::RegistratorWrapper<grammar::GNF < >, grammar::RightLG < > >(ToGNF::convert); - -grammar::RightRG < > ToGNF::convert(const grammar::RightRG < > & origGrammar) { - return origGrammar; -} - auto ToGNFRightRG = ToGNF::RegistratorWrapper<grammar::RightRG < >, grammar::RightRG < > >(ToGNF::convert); grammar::Grammar ToGNF::convert(const grammar::Grammar& grammar) { diff --git a/alib2algo/src/grammar/simplify/ToGNF.h b/alib2algo/src/grammar/simplify/ToGNF.h index aaa93afa54551faa25d3f3e2927d238b0f7921cb..89433bc78c4c33c8ad717d3395706e88db2e9b12 100644 --- a/alib2algo/src/grammar/simplify/ToGNF.h +++ b/alib2algo/src/grammar/simplify/ToGNF.h @@ -24,25 +24,161 @@ #include <grammar/Regular/RightLG.h> #include <grammar/Regular/RightRG.h> +#include "EpsilonRemover.h" +#include "SimpleRulesRemover.h" +#include "LeftRecursionRemover.h" +#include <grammar/convert/ToGrammarRightRG.h> +#include <common/createUnique.hpp> + namespace grammar { namespace simplify { class ToGNF : public std::SingleDispatch<ToGNF, grammar::Grammar, const grammar::GrammarBase &> { + template < class SymbolType > + static grammar::EpsilonFreeCFG < SymbolType > assignNonterminals(const grammar::EpsilonFreeCFG < SymbolType > & origGrammar); + template < class SymbolType > + static grammar::GNF < SymbolType > convertInternal( const grammar::EpsilonFreeCFG < SymbolType > & origGrammar ); + public: static grammar::Grammar convert( const grammar::Grammar & grammar ); - static grammar::GNF < > convert( const grammar::CFG < > & grammar ); - static grammar::GNF < > convert( const grammar::EpsilonFreeCFG < > & grammar ); - static grammar::GNF < > convert( const grammar::CNF < > & grammar ); - static grammar::GNF < > convert( const grammar::GNF < > & grammar ); - static grammar::GNF < > convert( const grammar::LG < > & grammar ); - static grammar::GNF < > convert( const grammar::LeftLG < > & grammar ); - static grammar::RightRG < > convert( const grammar::LeftRG < > & grammar ); - static grammar::GNF < > convert( const grammar::RightLG < > & grammar ); - static grammar::RightRG < > convert( const grammar::RightRG < > & grammar ); + template < class SymbolType > + static grammar::GNF < SymbolType > convert( const grammar::CFG < SymbolType > & grammar ); + template < class SymbolType > + static grammar::GNF < SymbolType > convert( const grammar::EpsilonFreeCFG < SymbolType > & grammar ); + template < class SymbolType > + static grammar::GNF < SymbolType > convert( const grammar::CNF < SymbolType > & grammar ); + template < class SymbolType > + static grammar::GNF < SymbolType > convert( const grammar::GNF < SymbolType > & grammar ); + template < class SymbolType > + static grammar::GNF < SymbolType > convert( const grammar::LG < SymbolType > & grammar ); + template < class SymbolType > + static grammar::GNF < SymbolType > convert( const grammar::LeftLG < SymbolType > & grammar ); + template < class SymbolType > + static grammar::RightRG < SymbolType > convert( const grammar::LeftRG < SymbolType > & grammar ); + template < class SymbolType > + static grammar::GNF < SymbolType > convert( const grammar::RightLG < SymbolType > & grammar ); + template < class SymbolType > + static grammar::RightRG < SymbolType > convert( const grammar::RightRG < SymbolType > & grammar ); }; +template < class SymbolType > +grammar::EpsilonFreeCFG < SymbolType > ToGNF::assignNonterminals(const grammar::EpsilonFreeCFG < SymbolType > & origGrammar) { + grammar::EpsilonFreeCFG < SymbolType > res(origGrammar.getInitialSymbol()); + res.setNonterminalAlphabet(origGrammar.getNonterminalAlphabet()); + res.setTerminalAlphabet(origGrammar.getTerminalAlphabet()); + res.setGeneratesEpsilon(origGrammar.getGeneratesEpsilon()); + + for(const std::pair<const alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>>& rule : origGrammar.getRules()) { + for(const std::vector<alphabet::Symbol>& singleRHS : rule.second) { + if(res.getTerminalAlphabet().count(singleRHS[0])) { //do not substitute terminals + res.addRule(rule.first, singleRHS); + continue; + } + const alphabet::Symbol& secondLHS = singleRHS[0]; + if(origGrammar.getRules().find(secondLHS) == origGrammar.getRules().end()) { //is there any right hand side to substitue with? + //if not well this rule does not generate anything anyway + continue; + } + + for(const std::vector<alphabet::Symbol>& secondSingleRHS : origGrammar.getRules().find(secondLHS)->second) { // do the substitution + std::vector<alphabet::Symbol> newRHS(secondSingleRHS); + newRHS.insert(newRHS.end(), singleRHS.begin() + 1, singleRHS.end()); + res.addRule(rule.first, newRHS); + } + } + } + return res; +} + +template < class SymbolType > +grammar::GNF < SymbolType > ToGNF::convertInternal( const grammar::EpsilonFreeCFG < SymbolType > & origGrammar ) { + grammar::EpsilonFreeCFG < SymbolType > step(origGrammar); + while(true) { + grammar::EpsilonFreeCFG < SymbolType > nextStep = assignNonterminals(step); + + if(step == nextStep) break; + step = std::move(nextStep); + } + + grammar::GNF < SymbolType > res(step.getInitialSymbol()); + res.setTerminalAlphabet(step.getTerminalAlphabet()); + res.setNonterminalAlphabet(step.getNonterminalAlphabet()); + res.setGeneratesEpsilon(step.getGeneratesEpsilon()); + std::map<alphabet::Symbol, alphabet::Symbol> terminalToPrimed; + for(const alphabet::Symbol& terminal : step.getTerminalAlphabet()) { + alphabet::Symbol primed = common::createUnique(terminal, res.getTerminalAlphabet(), res.getNonterminalAlphabet()); + terminalToPrimed.insert(std::make_pair(terminal, primed)); + res.addNonterminalSymbol(primed); + res.addRule(primed, std::make_pair(terminal, std::vector<alphabet::Symbol> {})); + } + for(const auto& rule : step.getRules()) { + for(const auto& rhs : rule.second) { + std::vector<alphabet::Symbol> convertedNonterminals; + bool first = true; + for(const alphabet::Symbol& rhsSymbol : rhs) { + if(first) { + first = false; + continue; + } + + if(res.getNonterminalAlphabet().count(rhsSymbol)) + convertedNonterminals.push_back(rhsSymbol); + else + convertedNonterminals.push_back(terminalToPrimed.find(rhsSymbol)->second); + } + res.addRule(rule.first, std::make_pair(rhs[0], std::move(convertedNonterminals))); + } + } + return res; +} + +template < class SymbolType > +grammar::GNF < SymbolType > ToGNF::convert(const grammar::CFG < SymbolType > & origGrammar) { + return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar)))); +} + +template < class SymbolType > +grammar::GNF < SymbolType > ToGNF::convert(const grammar::EpsilonFreeCFG < SymbolType > & origGrammar) { + return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(origGrammar))); +} + +template < class SymbolType > +grammar::GNF < SymbolType > ToGNF::convert(const grammar::CNF < SymbolType > & origGrammar) { + return convertInternal(grammar::simplify::LeftRecursionRemover::remove(origGrammar)); +} + +template < class SymbolType > +grammar::GNF < SymbolType > ToGNF::convert(const grammar::GNF < SymbolType > & origGrammar) { + return origGrammar; +} + +template < class SymbolType > +grammar::GNF < SymbolType > ToGNF::convert(const grammar::LG < SymbolType > & origGrammar) { + return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar)))); +} + +template < class SymbolType > +grammar::GNF < SymbolType > ToGNF::convert(const grammar::LeftLG < SymbolType > & origGrammar) { + return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar)))); +} + +template < class SymbolType > +grammar::RightRG < SymbolType > ToGNF::convert(const grammar::LeftRG < SymbolType > & origGrammar) { + return convert::ToGrammarRightRG::convert(origGrammar); +} + +template < class SymbolType > +grammar::GNF < SymbolType > ToGNF::convert(const grammar::RightLG < SymbolType > & origGrammar) { + return convertInternal(grammar::simplify::SimpleRulesRemover::remove(grammar::simplify::LeftRecursionRemover::remove(grammar::simplify::EpsilonRemover::remove(origGrammar)))); +} + +template < class SymbolType > +grammar::RightRG < SymbolType > ToGNF::convert(const grammar::RightRG < SymbolType > & origGrammar) { + return origGrammar; +} + } /* namespace simplify */ } /* namespace grammar */ diff --git a/alib2algo/src/grammar/simplify/Trim.cpp b/alib2algo/src/grammar/simplify/Trim.cpp index 00e8315afa00c4cee6f4131daf91163927e2d2f5..046d7fae063d6af0695462c051cb775e1723de26 100644 --- a/alib2algo/src/grammar/simplify/Trim.cpp +++ b/alib2algo/src/grammar/simplify/Trim.cpp @@ -7,28 +7,10 @@ #include "Trim.h" -#include <grammar/ContextFree/CFG.h> -#include <grammar/ContextFree/EpsilonFreeCFG.h> -#include <grammar/ContextFree/GNF.h> -#include <grammar/ContextFree/CNF.h> -#include <grammar/ContextFree/LG.h> -#include <grammar/Regular/LeftLG.h> -#include <grammar/Regular/LeftRG.h> -#include <grammar/Regular/RightLG.h> -#include <grammar/Regular/RightRG.h> - -#include "UnreachableSymbolsRemover.h" -#include "UnproductiveSymbolsRemover.h" - namespace grammar { namespace simplify { -template<class T> -T Trim::trim( const T & grammar ) { - return grammar::simplify::UnreachableSymbolsRemover::remove( grammar::simplify::UnproductiveSymbolsRemover::remove( grammar ) ); -} - auto TrimCFG = Trim::RegistratorWrapper<grammar::CFG < >, grammar::CFG < > >(Trim::trim); auto TrimEpsilonFreeCFG = Trim::RegistratorWrapper<grammar::EpsilonFreeCFG < >, grammar::EpsilonFreeCFG < > >(Trim::trim); auto TrimGNF = Trim::RegistratorWrapper<grammar::GNF < >, grammar::GNF < > >(Trim::trim); diff --git a/alib2algo/src/grammar/simplify/Trim.h b/alib2algo/src/grammar/simplify/Trim.h index 9c7137720b1e691ee26325f95de5616946329182..1f0f8b0868c7cd2ff2dec594b069b238a87939c8 100644 --- a/alib2algo/src/grammar/simplify/Trim.h +++ b/alib2algo/src/grammar/simplify/Trim.h @@ -11,6 +11,19 @@ #include <core/multipleDispatch.hpp> #include <grammar/Grammar.h> +#include <grammar/ContextFree/CFG.h> +#include <grammar/ContextFree/EpsilonFreeCFG.h> +#include <grammar/ContextFree/GNF.h> +#include <grammar/ContextFree/CNF.h> +#include <grammar/ContextFree/LG.h> +#include <grammar/Regular/LeftLG.h> +#include <grammar/Regular/LeftRG.h> +#include <grammar/Regular/RightLG.h> +#include <grammar/Regular/RightRG.h> + +#include "UnreachableSymbolsRemover.h" +#include "UnproductiveSymbolsRemover.h" + namespace grammar { namespace simplify { @@ -29,6 +42,11 @@ public: static T trim( const T & grammar ); }; +template<class T> +T Trim::trim( const T & grammar ) { + return grammar::simplify::UnreachableSymbolsRemover::remove( grammar::simplify::UnproductiveSymbolsRemover::remove( grammar ) ); +} + } /* namespace simplify */ } /* namespace grammar */ diff --git a/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.cpp b/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.cpp index 4e985f226a3075d12285a25cebf315eb2bb82eaf..ba8d91e10fd6f011807e06404ea3a753f29c5fd7 100644 --- a/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.cpp +++ b/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.cpp @@ -7,59 +7,10 @@ #include "UnproductiveSymbolsRemover.h" -#include <grammar/ContextFree/CFG.h> -#include <grammar/ContextFree/EpsilonFreeCFG.h> -#include <grammar/ContextFree/GNF.h> -#include <grammar/ContextFree/CNF.h> -#include <grammar/ContextFree/LG.h> -#include <grammar/Regular/LeftLG.h> -#include <grammar/Regular/LeftRG.h> -#include <grammar/Regular/RightLG.h> -#include <grammar/Regular/RightRG.h> - -#include <set> -#include <algorithm> - -#include "../properties/ProductiveNonterminals.h" -#include <exception/CommonException.h> - namespace grammar { namespace simplify { -template<class T> -T UnproductiveSymbolsRemover::remove( const T & grammar ) { - // 1. - std::set<alphabet::Symbol> Nt = grammar::properties::ProductiveNonterminals::getProductiveNonterminals( grammar ); - - T ret(grammar.getInitialSymbol( ) ); - - for( const auto & symbol : Nt ) - ret.addNonterminalSymbol( symbol ); - - for( const auto & symbol : grammar.getTerminalAlphabet( ) ) - ret.addTerminalSymbol( symbol ); - - const std::set<alphabet::Symbol> & terminals = ret.getTerminalAlphabet( ); - for( const auto & rule : grammar.getRawRules( ) ) { - if( Nt.count( rule.first ) ) { - for( const auto & rhs : rule.second ) { - if( all_of( rhs.begin( ), rhs.end( ), [ Nt, terminals ]( const alphabet::Symbol & symbol ) { - return Nt.count( symbol ) || terminals.count( symbol ); - } ) ) - ret.addRawRule( rule.first, rhs ); - } - } - } - - - /* if( ! G1.getNonTerminalSymbols( ) . count( grammar.getInitialSymbol( ) ) ) - throw CommonException( "Starting symbol of grammar was marked as unproductive and therefore it was removed." ); */ - - // 2. - return ret; -} - auto UnproductiveSymbolsRemoverCFG = UnproductiveSymbolsRemover::RegistratorWrapper<grammar::CFG < >, grammar::CFG < > >(UnproductiveSymbolsRemover::remove); auto UnproductiveSymbolsRemoverEpsilonFreeCFG = UnproductiveSymbolsRemover::RegistratorWrapper<grammar::EpsilonFreeCFG < >, grammar::EpsilonFreeCFG < > >(UnproductiveSymbolsRemover::remove); auto UnproductiveSymbolsRemoverGNF = UnproductiveSymbolsRemover::RegistratorWrapper<grammar::GNF < >, grammar::GNF < > >(UnproductiveSymbolsRemover::remove); diff --git a/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.h b/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.h index 04826f8d910f785198f16cceac0abf3683069f05..d35ce743925cb00153c0bfae3132eb9b3c0e979b 100644 --- a/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.h +++ b/alib2algo/src/grammar/simplify/UnproductiveSymbolsRemover.h @@ -11,6 +11,22 @@ #include <core/multipleDispatch.hpp> #include <grammar/Grammar.h> +#include <grammar/ContextFree/CFG.h> +#include <grammar/ContextFree/EpsilonFreeCFG.h> +#include <grammar/ContextFree/GNF.h> +#include <grammar/ContextFree/CNF.h> +#include <grammar/ContextFree/LG.h> +#include <grammar/Regular/LeftLG.h> +#include <grammar/Regular/LeftRG.h> +#include <grammar/Regular/RightLG.h> +#include <grammar/Regular/RightRG.h> + +#include <set> +#include <algorithm> + +#include <grammar/properties/ProductiveNonterminals.h> +#include <exception/CommonException.h> + namespace grammar { namespace simplify { @@ -25,10 +41,43 @@ public: /** * Removes unproductive (or useless - terminology) symbols - Melichar 3.12 */ - template<class T> + template < class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > > static T remove( const T & grammar ); }; +template < class T, class SymbolType > +T UnproductiveSymbolsRemover::remove( const T & grammar ) { + // 1. + std::set<SymbolType> Nt = grammar::properties::ProductiveNonterminals::getProductiveNonterminals( grammar ); + + T ret(grammar.getInitialSymbol( ) ); + + for( const auto & symbol : Nt ) + ret.addNonterminalSymbol( symbol ); + + for( const auto & symbol : grammar.getTerminalAlphabet( ) ) + ret.addTerminalSymbol( symbol ); + + const std::set<SymbolType> & terminals = ret.getTerminalAlphabet( ); + for( const auto & rule : grammar.getRawRules( ) ) { + if( Nt.count( rule.first ) ) { + for( const auto & rhs : rule.second ) { + if( all_of( rhs.begin( ), rhs.end( ), [ Nt, terminals ]( const SymbolType & symbol ) { + return Nt.count( symbol ) || terminals.count( symbol ); + } ) ) + ret.addRawRule( rule.first, rhs ); + } + } + } + + + /* if( ! G1.getNonTerminalSymbols( ) . count( grammar.getInitialSymbol( ) ) ) + throw CommonException( "Starting symbol of grammar was marked as unproductive and therefore it was removed." ); */ + + // 2. + return ret; +} + } /* namespace simplify */ } /* namespace grammar */ diff --git a/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.cpp b/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.cpp index e5917b667f2807d0f094348f168088550ef4b418..860b36a43a7a74afa3aa653b81527bf812aab35b 100644 --- a/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.cpp +++ b/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.cpp @@ -7,58 +7,10 @@ #include "UnreachableSymbolsRemover.h" -#include <grammar/ContextFree/CFG.h> -#include <grammar/ContextFree/EpsilonFreeCFG.h> -#include <grammar/ContextFree/GNF.h> -#include <grammar/ContextFree/CNF.h> -#include <grammar/ContextFree/LG.h> -#include <grammar/Regular/LeftLG.h> -#include <grammar/Regular/LeftRG.h> -#include <grammar/Regular/RightLG.h> -#include <grammar/Regular/RightRG.h> - -#include <set> -#include <algorithm> - -#include "../properties/UnreachableSymbols.h" - namespace grammar { namespace simplify { -template<class T> -T UnreachableSymbolsRemover::remove( const T & grammar) { - // 1. - std::set<alphabet::Symbol> Vt = grammar::properties::UnreachableSymbols::getUnreachableSymbols( grammar ); - - T ret(grammar.getInitialSymbol( ) ); - - std::set<alphabet::Symbol> newNonTerminals, newTerminals; - - set_intersection( Vt.begin( ), Vt.end( ), grammar.getNonterminalAlphabet( ).begin( ), grammar.getNonterminalAlphabet( ).end( ), std::inserter( newNonTerminals, newNonTerminals.begin( ) ) ); - for( const auto & symbol : newNonTerminals ) - ret.addNonterminalSymbol( symbol ); - - set_intersection( Vt.begin( ), Vt.end( ), grammar.getTerminalAlphabet( ).begin( ), grammar.getTerminalAlphabet( ).end( ), std::inserter( newTerminals, newTerminals.begin( ) ) ); - for( const auto & symbol : newTerminals ) - ret.addTerminalSymbol( symbol ); - - // A->\alpha: if A \in N' and \alpha in V_i*, then A->\alpha in P - for( const auto & rule : grammar.getRawRules( ) ) { - if( newNonTerminals.count( rule.first ) ) { - for( const auto& rhs : rule.second ) { - if( all_of( rhs.begin( ), rhs.end( ), [ Vt ]( alphabet::Symbol const& symb ) -> bool { - return Vt.count( symb ); - } ) ) - ret.addRawRule( rule.first, rhs ); - } - } - } - - // 2. - return ret; -} - auto UnreachableSymbolsRemoverCFG = UnreachableSymbolsRemover::RegistratorWrapper<grammar::CFG < >, grammar::CFG < > >(UnreachableSymbolsRemover::remove); auto UnreachableSymbolsRemoverEpsilonFreeCFG = UnreachableSymbolsRemover::RegistratorWrapper<grammar::EpsilonFreeCFG < >, grammar::EpsilonFreeCFG < > >(UnreachableSymbolsRemover::remove); auto UnreachableSymbolsRemoverGNF = UnreachableSymbolsRemover::RegistratorWrapper<grammar::GNF < >, grammar::GNF < > >(UnreachableSymbolsRemover::remove); diff --git a/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.h b/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.h index 603abfd9153ccd9b2a2546fbff8f64734279538c..cc94b276522883a7d14f44a2d706ea9c61c6df7b 100644 --- a/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.h +++ b/alib2algo/src/grammar/simplify/UnreachableSymbolsRemover.h @@ -11,6 +11,21 @@ #include <core/multipleDispatch.hpp> #include <grammar/Grammar.h> +#include <grammar/ContextFree/CFG.h> +#include <grammar/ContextFree/EpsilonFreeCFG.h> +#include <grammar/ContextFree/GNF.h> +#include <grammar/ContextFree/CNF.h> +#include <grammar/ContextFree/LG.h> +#include <grammar/Regular/LeftLG.h> +#include <grammar/Regular/LeftRG.h> +#include <grammar/Regular/RightLG.h> +#include <grammar/Regular/RightRG.h> + +#include <set> +#include <algorithm> + +#include <grammar/properties/UnreachableSymbols.h> + namespace grammar { namespace simplify { @@ -25,10 +40,43 @@ public: /* * Removes unreachable symbols - Melichar 3.9 */ - template<class T> + template < class T, class SymbolType = typename grammar::SymbolTypeOfGrammar < T > > static T remove( const T & grammar ); }; +template < class T, class SymbolType > +T UnreachableSymbolsRemover::remove( const T & grammar) { + // 1. + std::set<SymbolType> Vt = grammar::properties::UnreachableSymbols::getUnreachableSymbols( grammar ); + + T ret(grammar.getInitialSymbol( ) ); + + std::set<SymbolType> newNonTerminals, newTerminals; + + set_intersection( Vt.begin( ), Vt.end( ), grammar.getNonterminalAlphabet( ).begin( ), grammar.getNonterminalAlphabet( ).end( ), std::inserter( newNonTerminals, newNonTerminals.begin( ) ) ); + for( const auto & symbol : newNonTerminals ) + ret.addNonterminalSymbol( symbol ); + + set_intersection( Vt.begin( ), Vt.end( ), grammar.getTerminalAlphabet( ).begin( ), grammar.getTerminalAlphabet( ).end( ), std::inserter( newTerminals, newTerminals.begin( ) ) ); + for( const auto & symbol : newTerminals ) + ret.addTerminalSymbol( symbol ); + + // A->\alpha: if A \in N' and \alpha in V_i*, then A->\alpha in P + for( const auto & rule : grammar.getRawRules( ) ) { + if( newNonTerminals.count( rule.first ) ) { + for( const auto& rhs : rule.second ) { + if( all_of( rhs.begin( ), rhs.end( ), [ Vt ]( SymbolType const& symb ) -> bool { + return Vt.count( symb ); + } ) ) + ret.addRawRule( rule.first, rhs ); + } + } + } + + // 2. + return ret; +} + } /* namespace simplify */ } /* namespace grammar */