/* * Compaction.cpp * * Created on: 2. 11. 2014 * Author: Tomas Pecka */ #include "Compaction.h" #include <exception/AlibException.h> #include <automaton/common/State.h> #include <automaton/FSM/CompactNFA.h> #include <automaton/FSM/DFA.h> #include <stack> #include <tuple> namespace automaton { namespace transform { automaton::Automaton Compaction::convert(const automaton::Automaton& automaton) { automaton::Automaton* out = NULL; automaton.getData().Accept((void*) &out, Compaction::COMPACTION); automaton::Automaton res(std::move(*out)); delete out; return res; } automaton::CompactNFA Compaction::convert(const automaton::CompactNFA& automaton) { return automaton; } automaton::CompactNFA Compaction::convert(const automaton::DFA& automaton) { automaton::CompactNFA res(automaton.getInitialState()); res.setInputAlphabet(automaton.getInputAlphabet()); std::set<automaton::State> visited; std::stack<std::tuple<automaton::State, automaton::State, alphabet::Symbol>> stack; // state x lastFork x symbol we used to go to that state for(const auto& transition: automaton.getTransitionsFromState(automaton.getInitialState())) stack.push(std::make_tuple(transition.second, automaton.getInitialState(), transition.first.second)); if(automaton.getFinalStates().count(automaton.getInitialState()) > 0) res.addFinalState(automaton.getInitialState()); while(!stack.empty()) { automaton::State q = std::move(std::get<0>(stack.top())); automaton::State lastFork = std::move(std::get<1>(stack.top())); alphabet::Symbol symbol = std::move(std::get<2>(stack.top())); stack.pop(); string::LinearString path { automaton.getInputAlphabet(), { symbol } }; std::map<std::pair<automaton::State, alphabet::Symbol>, automaton::State> transitions; // only 1 child and nonfinal while((transitions = std::move(automaton.getTransitionsFromState(q))).size() == 1 && automaton.getFinalStates().count(q) == 0) { const std::pair<std::pair<automaton::State, alphabet::Symbol>, automaton::State>& transition = * transitions.begin(); path.appendSymbol(transition.first.second); q = transition.second; } // fork or final state res.addState(q); if(automaton.getFinalStates().count(q)) res.addFinalState(q); res.addTransition(lastFork, path, q); for(const std::pair<std::pair<automaton::State, alphabet::Symbol>, automaton::State>& transition : automaton.getTransitionsFromState(q)) if(visited.insert(transition.second).second) stack.push(std::make_tuple(transition.second, q, transition.first.second)); } return res; } automaton::CompactNFA Compaction::convert(const automaton::NFA& automaton) { automaton::CompactNFA res(automaton.getInitialState()); // TODO return res; } void Compaction::Visit(void* data, const CompactNFA& automaton) const { automaton::Automaton*& out = *((automaton::Automaton**) data); out = new automaton::Automaton(this->convert(automaton)); } void Compaction::Visit(void* data, const DFA& automaton) const { automaton::Automaton*& out = *((automaton::Automaton**) data); out = new automaton::Automaton(this->convert(automaton)); } void Compaction::Visit(void*, const EpsilonNFA&) const { throw exception::AlibException("Unsupported automaton type EpsilonNFA"); } void Compaction::Visit(void*, const ExtendedNFA&) const { throw exception::AlibException("Unsupported automaton type ExtendedNFA"); } void Compaction::Visit(void*, const MultiInitialStateNFA&) const { throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA"); } void Compaction::Visit(void* data, const NFA& automaton) const { automaton::Automaton*& out = *((automaton::Automaton**) data); out = new automaton::Automaton(this->convert(automaton)); } const Compaction Compaction::COMPACTION; } /* namespace transform */ } /* namespace automaton */