void ObservationTable::_buildLexicalRules(ContextFreeGrammar& G, map<NonTerminal, StringSet>& binaryRulesData, map<ContextSet, NonTerminal>& distributionNonTerminal) { EquivalenceClasses equivalenceClassesK = this->_getEquivalenceClasses(); EquivalenceClasses equivalenceClassesKK = this->_getEquivalenceClasses(false); // Let V be the set of these equivalence classes - set of non terminals for (EquivalenceClass equivalenceClassK : equivalenceClassesK) { //TWEAK Avoid unnecessary processing if (equivalenceClassK.first.size() == 0) { continue; } // Check if this equivalence class can generate a start symbol bool isStart = true; for (string w : equivalenceClassK.second) { if (this->D.find(w) == this->D.end()) { // Not found isStart = false; } } // Create the non-terminal for this equivalence class NonTerminal nonTerminal = isStart ? G.getStartSymbol() : G.getNonTerminalSymbol(); if (isStart) { G.I.insert(nonTerminal); } G.V.insert(nonTerminal); distributionNonTerminal.insert({ equivalenceClassK.first, nonTerminal }); // Save equivalence classes auto equivalenceClassesKKlocal = equivalenceClassesKK.find(equivalenceClassK.first); if (equivalenceClassesKKlocal == equivalenceClassesKK.end()) { // Not found G.getEquivalenceClasses().insert({ nonTerminal, equivalenceClassK.second }); } else { // Insert equivalence classes from KK G.getEquivalenceClasses().insert({ nonTerminal, equivalenceClassesKKlocal->second }); } // Compute lexical rules for (string w : equivalenceClassK.second) { if (w == this->_lambda || this->_alphabet.in(w)) { // terminal or lambda Production p(nonTerminal, new Terminal(w)); G.P.insert(p); G.Sigma.insert(Terminal(w)); G.getLexicalRules().insert({ w, nonTerminal }); continue; } // Remember the strings that will become binary rules auto binaryRuleData = binaryRulesData.find(nonTerminal); if (binaryRuleData != binaryRulesData.end()) { binaryRuleData->second.insert(w); } else { binaryRulesData.insert({ nonTerminal, { w } }); } } } }
ObservationTable::EquivalenceClasses ObservationTable::_getEquivalenceClasses(bool ofK) { EquivalenceClasses equivalenceClasses; StringSet& localK = ofK ? this->K : this->_KK; // Divide K into equivalence classes according to \equiv F for (string k : localK) { ContextSet distribution = this->_getDistributionByK(k); auto equivalenceClass = equivalenceClasses.find(distribution); if (equivalenceClass != equivalenceClasses.end()) { // Found equivalenceClass->second.insert(k); } else { // Not found StringSet ks; // set of k strings ks.insert(k); equivalenceClasses.insert({ distribution, ks }); } } return equivalenceClasses; }