Speed up mssc

This commit is contained in:
Robin Jadoul 2016-05-24 18:09:38 +02:00
parent 8ed2fd41e1
commit 8a59d19e5c
2 changed files with 23 additions and 8 deletions

View File

@ -34,6 +34,9 @@ namespace lxs {
struct ENFA : public NFA { struct ENFA : public NFA {
std::map<State, std::set<State> > epsilonTransitions; std::map<State, std::set<State> > epsilonTransitions;
virtual std::set<State> eClose(State) const; virtual std::set<State> eClose(State) const;
private:
mutable std::map<State, std::set<State> > eCloseCache;
}; };
std::string toDot(const DFA& d); std::string toDot(const DFA& d);

View File

@ -98,6 +98,10 @@ namespace lxs {
} }
std::set<State> ENFA::eClose(State s) const { std::set<State> ENFA::eClose(State s) const {
auto cachedIt = eCloseCache.find(s);
if (cachedIt != eCloseCache.end()) {
return cachedIt->second;
}
std::set<State> states; std::set<State> states;
std::queue<State> statequeue; std::queue<State> statequeue;
statequeue.push(s); statequeue.push(s);
@ -114,7 +118,7 @@ namespace lxs {
} }
} }
} }
return states; return eCloseCache[s] = states;
} }
std::set<State> NFA::eClose(State s) const { std::set<State> NFA::eClose(State s) const {
@ -282,9 +286,9 @@ namespace lxs {
namespace { // Utility function for mssc namespace { // Utility function for mssc
std::set<State> getNextState(std::set<State> oldstate, char symbol, const NFA& e) { std::set<State> getNextState(const std::set<State>& oldstate, char symbol, const NFA& e) {
std::set<State> states; std::set<State> states;
for(auto &state: oldstate) { for(const auto &state: oldstate) {
auto a = e.delta.find(state); auto a = e.delta.find(state);
if(a != e.delta.end()) { if(a != e.delta.end()) {
auto newStates = a->second.find(symbol); auto newStates = a->second.find(symbol);
@ -306,26 +310,34 @@ namespace lxs {
DFA mssc(const NFA& e) { DFA mssc(const NFA& e) {
//Temporary, improper dfa structure //Temporary, improper dfa structure
std::map<std::set<State>,std::map<char,std::set<State> > > dfa; std::map<std::set<State>, std::map<char,std::set<State> > > dfa;
std::map<char, std::set<State> > trans; std::map<char, std::set<State> > trans;
for (int c = 0; c < 256; c++) { for (int c = 0; c < 256; c++) {
trans[c] = {}; trans[c] = {};
} }
dfa[{}] = trans; dfa[{}] = trans;
std::set<char> usedChars;
for (const auto& stateTrans : e.delta) {
for (const auto& tr : stateTrans.second) {
usedChars.insert(tr.first);
}
}
//Lazy evaluation, on a still implicit DFA //Lazy evaluation, on a still implicit DFA
std::queue<std::set<State> > tocheck; std::queue<std::set<State> > tocheck;
tocheck.push(e.eClose(e.starting)); tocheck.push(e.eClose(e.starting));
while(!tocheck.empty()) { while(!tocheck.empty()) {
auto state = tocheck.front(); auto state = std::move(tocheck.front());
tocheck.pop(); tocheck.pop();
std::map<char, std::set<State> > trans; std::map<char, std::set<State> > trans;
for (int c = 0; c < 256; c++) { for (char c : usedChars) {
auto nextstate = getNextState(state,c,e); auto nextstate = getNextState(state,c,e);
trans[c] = nextstate;
if(dfa.find(nextstate) == dfa.end()) { if(dfa.find(nextstate) == dfa.end()) {
dfa[nextstate] = {};
tocheck.push(nextstate); tocheck.push(nextstate);
} }
trans[c] = std::move(nextstate);
} }
dfa[state] = trans; dfa[state] = trans;
} }