From 8a59d19e5c402256db416d9847906286f8b0fa8f Mon Sep 17 00:00:00 2001 From: Robin Jadoul Date: Tue, 24 May 2016 18:09:38 +0200 Subject: [PATCH] Speed up mssc --- include/Lexesis/automata.h | 3 +++ src/automata.cpp | 28 ++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/include/Lexesis/automata.h b/include/Lexesis/automata.h index 67d4680..f54a36d 100644 --- a/include/Lexesis/automata.h +++ b/include/Lexesis/automata.h @@ -34,6 +34,9 @@ namespace lxs { struct ENFA : public NFA { std::map > epsilonTransitions; virtual std::set eClose(State) const; + + private: + mutable std::map > eCloseCache; }; std::string toDot(const DFA& d); diff --git a/src/automata.cpp b/src/automata.cpp index c55ee61..3c1ef24 100644 --- a/src/automata.cpp +++ b/src/automata.cpp @@ -98,6 +98,10 @@ namespace lxs { } std::set ENFA::eClose(State s) const { + auto cachedIt = eCloseCache.find(s); + if (cachedIt != eCloseCache.end()) { + return cachedIt->second; + } std::set states; std::queue statequeue; statequeue.push(s); @@ -114,7 +118,7 @@ namespace lxs { } } } - return states; + return eCloseCache[s] = states; } std::set NFA::eClose(State s) const { @@ -282,9 +286,9 @@ namespace lxs { namespace { // Utility function for mssc - std::set getNextState(std::set oldstate, char symbol, const NFA& e) { + std::set getNextState(const std::set& oldstate, char symbol, const NFA& e) { std::set states; - for(auto &state: oldstate) { + for(const auto &state: oldstate) { auto a = e.delta.find(state); if(a != e.delta.end()) { auto newStates = a->second.find(symbol); @@ -306,26 +310,34 @@ namespace lxs { DFA mssc(const NFA& e) { //Temporary, improper dfa structure - std::map,std::map > > dfa; + std::map, std::map > > dfa; std::map > trans; for (int c = 0; c < 256; c++) { trans[c] = {}; } dfa[{}] = trans; - + + std::set usedChars; + for (const auto& stateTrans : e.delta) { + for (const auto& tr : stateTrans.second) { + usedChars.insert(tr.first); + } + } + //Lazy evaluation, on a still implicit DFA std::queue > tocheck; tocheck.push(e.eClose(e.starting)); while(!tocheck.empty()) { - auto state = tocheck.front(); + auto state = std::move(tocheck.front()); tocheck.pop(); std::map > trans; - for (int c = 0; c < 256; c++) { + for (char c : usedChars) { auto nextstate = getNextState(state,c,e); - trans[c] = nextstate; if(dfa.find(nextstate) == dfa.end()) { + dfa[nextstate] = {}; tocheck.push(nextstate); } + trans[c] = std::move(nextstate); } dfa[state] = trans; }