From 99065a1fa28cbb82573bc59257bd73cecd03ca9a Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Sat, 25 Oct 2014 12:27:42 +0200 Subject: [PATCH] Make normalization working with DPDA as well --- .../src/automaton/simplify/Normalize.cpp | 184 ++++++++++++++++-- alib2algo/src/automaton/simplify/Normalize.h | 36 +++- anormalize2/src/anormalize.cpp | 15 +- 3 files changed, 206 insertions(+), 29 deletions(-) diff --git a/alib2algo/src/automaton/simplify/Normalize.cpp b/alib2algo/src/automaton/simplify/Normalize.cpp index 1780efd450..37bc52557b 100644 --- a/alib2algo/src/automaton/simplify/Normalize.cpp +++ b/alib2algo/src/automaton/simplify/Normalize.cpp @@ -24,45 +24,53 @@ namespace automaton { namespace simplify { -automaton::DFA Normalize::normalize(automaton::DFA& fsm) { +automaton::Automaton Normalize::normalize(const automaton::Automaton& automaton) { + automaton::Automaton* out = NULL; + automaton.getData().Accept((void*) &out, Normalize::NORMALIZE); + automaton::Automaton res = std::move(*out); + delete out; + return res; +} + +automaton::DFA Normalize::normalize(const automaton::DFA& fsm) { int counter = 0; std::map<automaton::State, int > normalizationData; std::deque<automaton::State > processingData; - - normalizationData.insert(std::pair<automaton::State, int>(fsm.getInitialState(), counter++)); + + normalizationData.insert(std::make_pair(fsm.getInitialState(), counter++)); processingData.push_back(fsm.getInitialState()); - + while(!processingData.empty()) { automaton::State current = processingData.front(); processingData.pop_front(); - + std::map<std::pair<automaton::State, alphabet::Symbol>, automaton::State> transitionsMap = fsm.getTransitionsFromState(current); // Transitions are trivialy sorted by input symbol (from state is the same) - - for(auto iter = fsm.getTransitions().begin(); iter != fsm.getTransitions().end(); iter++) { + + for(auto iter = transitionsMap.begin(); iter != transitionsMap.end(); iter++) { if(normalizationData.find(iter->second) == normalizationData.end()) { normalizationData.insert(std::pair<automaton::State, int>(iter->second, counter++)); processingData.push_back(iter->second); } } } - + if(normalizationData.size() != fsm.getStates().size()) { throw exception::AlibException("Automaton normalize require minimal deterministic finite automaton"); } - + automaton::DFA result(automaton::State(normalizationData.find(fsm.getInitialState())->second)); - + result.setInputSymbols(fsm.getInputAlphabet()); - + for(auto iter = fsm.getStates().begin(); iter != fsm.getStates().end(); iter++) { result.addState(automaton::State(normalizationData.find(*iter)->second)); } - + for(auto iter = fsm.getFinalStates().begin(); iter != fsm.getFinalStates().end(); iter++) { result.addFinalState(automaton::State(normalizationData.find(*iter)->second)); } - + for(auto iter = fsm.getTransitions().begin(); iter != fsm.getTransitions().end(); iter++) { result.addTransition(automaton::State(normalizationData.find(iter->first.first)->second), iter->first.second, automaton::State(normalizationData.find(iter->second)->second)); } @@ -70,6 +78,156 @@ automaton::DFA Normalize::normalize(automaton::DFA& fsm) { return result; } +automaton::DPDA Normalize::normalize(const automaton::DPDA& pda) { + int counterState = 0; + std::map<automaton::State, int > normalizationDataState; + int counterSymbol = 0; + std::map<alphabet::Symbol, int > normalizationDataSymbol; + std::deque< automaton::State > processingData; + + normalizationDataState.insert(std::make_pair(pda.getInitialState(), counterState++)); + normalizationDataSymbol.insert(std::make_pair(pda.getInitialSymbol(), counterSymbol++)); + processingData.push_back(pda.getInitialState()); + + while(!processingData.empty()) { + automaton::State current = processingData.front(); + processingData.pop_front(); + + std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::pair<State, std::vector<alphabet::Symbol> > > transitionsMap = pda.getTransitionsFromState(current); + std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol> >, std::set< std::pair<std::vector< alphabet::Symbol >, std::pair<State, std::vector<alphabet::Symbol > > > > > transform; + + for(auto iter = transitionsMap.begin(); iter != transitionsMap.end(); iter++) { + transform[std::make_pair(std::get<0>(iter->first), std::get<1>(iter->first))].insert(std::make_pair(std::get<2>(iter->first), iter->second)); + } + // Transitions are trivialy sorted by input symbol (from state is the same) + + for(const auto& iter : transform) { + bool sign = false; + for(const auto& iter2 : iter.second) { + bool tmp = std::all_of(iter2.first.begin(), iter2.first.end(), [&](const alphabet::Symbol& symbol) { return normalizationDataSymbol.find(symbol) != normalizationDataSymbol.end(); }); + if( tmp ) { + if( normalizationDataState.find(iter2.second.first) == normalizationDataState.end() ) { + normalizationDataState.insert(std::make_pair(iter2.second.first, counterState++)); + processingData.push_back(iter2.second.first); + } + for(const auto& iter3 : iter2.second.second) { + if( normalizationDataSymbol.find(iter3) == normalizationDataSymbol.end() ) { + normalizationDataSymbol.insert(std::make_pair(iter3, counterSymbol++)); + } + } + } else { + sign = true; + } + } + if(sign) { + processingData.push_back(iter.first.first); + } + } + } + + if(normalizationDataState.size() != pda.getStates().size() || normalizationDataSymbol.size() != pda.getStackAlphabet().size()) { + throw exception::AlibException("Automaton normalize require connected deterministic pushdown automaton"); + } + + automaton::DPDA result(automaton::State(normalizationDataState.find(pda.getInitialState())->second), alphabet::symbolFrom(normalizationDataSymbol.find(pda.getInitialSymbol())->second)); + + result.setInputSymbols(pda.getInputAlphabet()); + + for(auto iter = pda.getStackAlphabet().begin(); iter != pda.getStackAlphabet().end(); iter++) { + result.addStackSymbol(alphabet::symbolFrom(normalizationDataSymbol.find(*iter)->second)); + } + + for(auto iter = pda.getStates().begin(); iter != pda.getStates().end(); iter++) { + result.addState(automaton::State(normalizationDataState.find(*iter)->second)); + } + + for(auto iter = pda.getFinalStates().begin(); iter != pda.getFinalStates().end(); iter++) { + result.addFinalState(automaton::State(normalizationDataState.find(*iter)->second)); + } + + for(auto iter = pda.getTransitions().begin(); iter != pda.getTransitions().end(); iter++) { + std::vector<alphabet::Symbol> pop; + for(const auto& elem : std::get<2>(iter->first)) { + pop.push_back(alphabet::symbolFrom(normalizationDataSymbol.find(elem)->second)); + } + std::vector<alphabet::Symbol> push; + for(const auto& elem : iter->second.second) { + push.push_back(alphabet::symbolFrom(normalizationDataSymbol.find(elem)->second)); + } + result.addTransition(automaton::State(normalizationDataState.find(std::get<0>(iter->first))->second), std::get<1>(iter->first), pop, automaton::State(normalizationDataState.find(iter->second.first)->second), push); + } + + return result; +} + +void Normalize::Visit(void*, const automaton::EpsilonNFA&) const { + throw exception::AlibException("Unsupported automaton type EpsilonNFA"); +} + +void Normalize::Visit(void* data, const automaton::DFA& automaton) const { + automaton::Automaton* & out = *((automaton::Automaton**) data); + out = new automaton::Automaton(this->normalize(automaton)); +} + +void Normalize::Visit(void*, const automaton::MultiInitialStateNFA&) const { + throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA"); +} + +void Normalize::Visit(void*, const automaton::NFA&) const { + throw exception::AlibException("Unsupported automaton type DFA"); +} + +void Normalize::Visit(void*, const automaton::ExtendedNFA& ) const { + throw exception::AlibException("Unsupported automaton type ExtendedNFA"); +} + +void Normalize::Visit(void*, const automaton::CompactNFA& ) const { + throw exception::AlibException("Unsupported automaton type CompactNFA"); +} + +void Normalize::Visit(void* data, const automaton::DPDA& automaton) const { + automaton::Automaton* & out = *((automaton::Automaton**) data); + out = new automaton::Automaton(this->normalize(automaton)); +} + +void Normalize::Visit(void*, const automaton::SinglePopDPDA&) const { + throw exception::AlibException("Unsupported automaton type SinglePopDPDA"); +} + +void Normalize::Visit(void*, const automaton::InputDrivenNPDA&) const { + throw exception::AlibException("Unsupported automaton type InputDrivenNPDA"); +} + +void Normalize::Visit(void*, const automaton::VisiblyPushdownDPDA&) const { + throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA"); +} + +void Normalize::Visit(void*, const automaton::VisiblyPushdownNPDA&) const { + throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA"); +} + +void Normalize::Visit(void*, const automaton::RealTimeHeightDeterministicDPDA&) const { + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA"); +} + +void Normalize::Visit(void*, const automaton::RealTimeHeightDeterministicNPDA&) const { + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA"); +} + +void Normalize::Visit(void*, const automaton::NPDA&) const { + throw exception::AlibException("Unsupported automaton type NPDA"); +} + +void Normalize::Visit(void*, const automaton::SinglePopNPDA&) const { + throw exception::AlibException("Unsupported automaton type SinglePopNPDA"); +} + +void Normalize::Visit(void*, const automaton::OneTapeDTM&) const { + throw exception::AlibException("Unsupported automaton type OneTapeDTM"); +} + +const Normalize Normalize::NORMALIZE; + } /* namespace simplify */ } /* namespace automaton */ diff --git a/alib2algo/src/automaton/simplify/Normalize.h b/alib2algo/src/automaton/simplify/Normalize.h index 48a6df5a2e..79523da733 100644 --- a/alib2algo/src/automaton/simplify/Normalize.h +++ b/alib2algo/src/automaton/simplify/Normalize.h @@ -8,16 +8,44 @@ #ifndef NORMALIZE_H_ #define NORMALIZE_H_ -#include "automaton/FSM/DFA.h" +#include <automaton/FSM/DFA.h> +#include <automaton/PDA/DPDA.h> +#include <automaton/Automaton.h> namespace automaton { namespace simplify { -class Normalize { +class Normalize : public automaton::VisitableAutomatonBase::const_visitor_type { public: - static automaton::DFA normalize(automaton::DFA& dfa); - + /** + * @param dfa automaton to normalize + */ + static automaton::Automaton normalize(const automaton::Automaton& dfa); + + static automaton::DFA normalize(const automaton::DFA& dfa); + static automaton::DPDA normalize(const automaton::DPDA& dfa); + + +protected: + void Visit(void*, const automaton::EpsilonNFA& automaton) const; + void Visit(void*, const automaton::MultiInitialStateNFA& automaton) const; + void Visit(void*, const automaton::NFA& automaton) const; + void Visit(void*, const automaton::DFA& automaton) const; + void Visit(void*, const automaton::ExtendedNFA& automaton) const; + void Visit(void*, const automaton::CompactNFA& automaton) const; + void Visit(void*, const automaton::DPDA& automaton) const; + void Visit(void*, const automaton::SinglePopDPDA& automaton) const; + void Visit(void*, const automaton::InputDrivenNPDA& automaton) const; + void Visit(void*, const automaton::VisiblyPushdownDPDA& automaton) const; + void Visit(void*, const automaton::VisiblyPushdownNPDA& automaton) const; + void Visit(void*, const automaton::RealTimeHeightDeterministicDPDA& automaton) const; + void Visit(void*, const automaton::RealTimeHeightDeterministicNPDA& automaton) const; + void Visit(void*, const automaton::NPDA& automaton) const; + void Visit(void*, const automaton::SinglePopNPDA& automaton) const; + void Visit(void*, const automaton::OneTapeDTM& automaton) const; + + static const Normalize NORMALIZE; }; } /* namespace simplify */ diff --git a/anormalize2/src/anormalize.cpp b/anormalize2/src/anormalize.cpp index 66763a09ae..34483b8ba6 100644 --- a/anormalize2/src/anormalize.cpp +++ b/anormalize2/src/anormalize.cpp @@ -14,26 +14,17 @@ int main(int argc, char** argv) { try { - - automaton::DFA* automatonPointer = NULL; - if (argc == 2 && std::string("-h").compare(argv[1]) == 0) { std::cout << "Automaton normalize." << std::endl << "Usage: anormalize automaton.xml" << std::endl; return -1; } else if (argc == 1 || (argc == 2 && std::string("--").compare(argv[1]) == 0)) { - automatonPointer = static_cast<automaton::DFA*>(std::move(alib::DataFactory::fromStdin<automaton::DFA>()).plunder()); + alib::DataFactory::toStdout(automaton::simplify::Normalize::normalize(alib::DataFactory::fromStdin<automaton::Automaton>())); } else if (argc == 2) { - automatonPointer = static_cast<automaton::DFA*>(std::move(alib::DataFactory::fromFile<automaton::DFA>(argv[1])).plunder()); + alib::DataFactory::toStdout(automaton::simplify::Normalize::normalize(alib::DataFactory::fromFile<automaton::Automaton>(argv[1]))); } else { - std::cout << "Automaton normalize require deterministic finite automaton" << std::endl; + std::cout << "Automaton normalize require deterministic automaton" << std::endl; return 1; } - - automaton::DFA res = automaton::simplify::Normalize::normalize(*automatonPointer); - alib::DataFactory::toStdout(res); - - delete automatonPointer; - return 0; } catch (const exception::AlibException& exception) { -- GitLab