diff --git a/aconversions2/src/ConversionHandler.cpp b/aconversions2/src/ConversionHandler.cpp index a3c7a957a7330689682f54624ce715b59e6ae477..f7f86ee440d826fe75905c5ff8ede06975f00bb3 100644 --- a/aconversions2/src/ConversionHandler.cpp +++ b/aconversions2/src/ConversionHandler.cpp @@ -143,7 +143,7 @@ void ConversionHandler::convertFSMtoRG( void ) void ConversionHandler::convertFSMtoRRG( void ) { - const automaton::NFA fsm = alib::DataFactory::fromTokens<automaton::NFA>( m_tokens ); + const automaton::Automaton fsm = alib::DataFactory::fromTokens<automaton::Automaton>( m_tokens ); switch( m_algorithm ) { @@ -157,7 +157,7 @@ void ConversionHandler::convertFSMtoRRG( void ) void ConversionHandler::convertFSMtoLRG( void ) { - const automaton::NFA fsm = alib::DataFactory::fromTokens<automaton::NFA>( m_tokens ); + const automaton::Automaton fsm = alib::DataFactory::fromTokens<automaton::Automaton>( m_tokens ); switch( m_algorithm ) { diff --git a/alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.cpp b/alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.cpp index aa02f307715808e587806dcc4c8b2026161a5e5a..18198fb05a4172ab3c9698b0910b9c8e8d3afec3 100644 --- a/alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.cpp +++ b/alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.cpp @@ -4,55 +4,153 @@ #include <label/StringLabel.h> #include <alphabet/LabeledSymbol.h> +#include <exception/AlibException.h> + namespace fa2rg { grammar::LeftRG FAtoLRGConverter::convert(const automaton::NFA& automaton) { - std::map<automaton::State, alphabet::Symbol> nonterminalMap; - // step 2 - grammar::LeftRG grammar(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("S"))))); + std::map<automaton::State, alphabet::Symbol> nonterminalMap; + // step 2 + grammar::LeftRG grammar(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("S"))))); + + // step 1 + grammar.setTerminalAlphabet(automaton.getInputAlphabet()); + + for(const auto& state : automaton.getStates()) + { + alphabet::Symbol nt = alphabet::createUniqueSymbol(alphabet::Symbol(alphabet::LabeledSymbol(state.getName())), grammar.getTerminalAlphabet(), grammar.getNonterminalAlphabet()); + grammar.addNonterminalSymbol(nt); + nonterminalMap.insert(std::pair<automaton::State, alphabet::Symbol>(state, nt)); + } + + + // step 3 - create set of P in G + for(const auto& transition : automaton.getTransitions()) + { + const automaton::State& from = transition.first.first; + const alphabet::Symbol& input = transition.first.second; + + for(const auto& to : transition.second) + { + // 3a + grammar.addRule(nonterminalMap.find(to)->second, std::make_pair(nonterminalMap.find(from)->second, input)); + + if(automaton.getFinalStates().count(to) > 0) + grammar.addRule(grammar.getInitialSymbol(), std::make_pair(nonterminalMap.find(from)->second, input)); + + + if(automaton.getInitialStates().count(from) > 0) + { + grammar.addRule(nonterminalMap.find(to)->second, input); + + if(automaton.getFinalStates().count(to) > 0) + grammar.addRule(grammar.getInitialSymbol(), input); + } + } + } + + for(const auto & initial : automaton.getInitialStates()) { + if(automaton.getFinalStates().count(initial) > 0) + grammar.setGeneratesEpsilon(true); + } + + return grammar; +} + +grammar::LeftRG FAtoLRGConverter::convert(const automaton::DFA& automaton) +{ + std::map<automaton::State, alphabet::Symbol> nonterminalMap; + // step 2 + grammar::LeftRG grammar(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("S"))))); + + // step 1 + grammar.setTerminalAlphabet(automaton.getInputAlphabet()); + + for(const auto& state : automaton.getStates()) + { + alphabet::Symbol nt = alphabet::createUniqueSymbol(alphabet::Symbol(alphabet::LabeledSymbol(state.getName())), grammar.getTerminalAlphabet(), grammar.getNonterminalAlphabet()); + grammar.addNonterminalSymbol(nt); + nonterminalMap.insert(std::pair<automaton::State, alphabet::Symbol>(state, nt)); + } + - // step 1 - grammar.setTerminalAlphabet(automaton.getInputAlphabet()); + // step 3 - create set of P in G + for(const auto& transition : automaton.getTransitions()) + { + const automaton::State& from = transition.first.first; + const alphabet::Symbol& input = transition.first.second; + const automaton::State& to = transition.second; - for(const auto& state : automaton.getStates()) - { - alphabet::Symbol nt = alphabet::createUniqueSymbol(alphabet::Symbol(alphabet::LabeledSymbol(state.getName())), grammar.getTerminalAlphabet(), grammar.getNonterminalAlphabet()); - grammar.addNonterminalSymbol(nt); - nonterminalMap.insert(std::pair<automaton::State, alphabet::Symbol>(state, nt)); - } + // 3a + grammar.addRule(nonterminalMap.find(to)->second, std::make_pair(nonterminalMap.find(from)->second, input)); + if(automaton.getFinalStates().count(to) > 0) + grammar.addRule(grammar.getInitialSymbol(), std::make_pair(nonterminalMap.find(from)->second, input)); - // step 3 - create set of P in G - for(const auto& transition : automaton.getTransitions()) - { - const automaton::State& from = transition.first.first; - const alphabet::Symbol& input = transition.first.second; - for(const auto& to : transition.second) - { - // 3a - grammar.addRule(nonterminalMap.find(to)->second, std::make_pair(nonterminalMap.find(from)->second, input)); + if(automaton.getInitialState() == from) + { + grammar.addRule(nonterminalMap.find(to)->second, input); - if(automaton.getFinalStates().count(to) > 0) - grammar.addRule(grammar.getInitialSymbol(), std::make_pair(nonterminalMap.find(from)->second, input)); + if(automaton.getFinalStates().count(to) > 0) + grammar.addRule(grammar.getInitialSymbol(), input); + } + } + if(automaton.getFinalStates().count(automaton.getInitialState()) > 0) + grammar.setGeneratesEpsilon(true); - if(automaton.getInitialStates().count(from) > 0) - { - grammar.addRule(nonterminalMap.find(to)->second, input); + return grammar; +} + +grammar::Grammar FAtoLRGConverter::convert(const automaton::Automaton& automaton) { + grammar::Grammar* out = NULL; + automaton.getData().Accept((void*) &out, FAtoLRGConverter::FA_TO_LRG_CONVERTER); + grammar::Grammar res = std::move(*out); + delete out; + return res; +} + +void FAtoLRGConverter::Visit(void*, const automaton::UnknownAutomaton&) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} + +void FAtoLRGConverter::Visit(void*, const automaton::EpsilonNFA& ) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} + +void FAtoLRGConverter::Visit(void* data, const automaton::NFA& automaton) const { + grammar::Grammar* & out = *((grammar::Grammar**) data); + out = new grammar::Grammar(this->convert(automaton)); +} - if(automaton.getFinalStates().count(to) > 0) - grammar.addRule(grammar.getInitialSymbol(), input); - } - } - } +void FAtoLRGConverter::Visit(void* data, const automaton::DFA& automaton) const { + grammar::Grammar* & out = *((grammar::Grammar**) data); + out = new grammar::Grammar(this->convert(automaton)); +} - if(automaton.getFinalStates().count(*automaton.getInitialStates().begin()) > 0) - grammar.setGeneratesEpsilon(true); +void FAtoLRGConverter::Visit(void*, const automaton::ExtendedNFA& ) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} - return grammar; +void FAtoLRGConverter::Visit(void*, const automaton::CompactNFA& ) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); } +void FAtoLRGConverter::Visit(void*, const automaton::NPDA&) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} + +void FAtoLRGConverter::Visit(void*, const automaton::SinglePopNPDA&) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} + +void FAtoLRGConverter::Visit(void*, const automaton::OneTapeDTM&) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} + +const FAtoLRGConverter FAtoLRGConverter::FA_TO_LRG_CONVERTER; + } /* namespace fa2rg */ diff --git a/alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.h b/alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.h index ef2f0a32ac70af252448548b085a74bb8c6d7fe9..c7e3bbbff8bae134ac8c1a8f38c6b3fdf15bf510 100644 --- a/alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.h +++ b/alib2algo/src/conversions/fa2rg/fa2lrg/FAtoLRGConverter.h @@ -1,10 +1,12 @@ #ifndef __FATOLRGCONVERTER_H__ #define __FATOLRGCONVERTER_H__ -#include <map> - #include <grammar/Regular/LeftRG.h> #include <automaton/FSM/NFA.h> +#include <automaton/FSM/DFA.h> + +#include <grammar/Grammar.h> +#include <automaton/Automaton.h> namespace fa2rg { @@ -13,14 +15,30 @@ namespace fa2rg * Finite automaton to right regular grammar converter. * Source: My own :) */ -class FAtoLRGConverter +class FAtoLRGConverter : public automaton::VisitableAutomatonBase::const_visitor_type { public: - /** - * Performs conversion. - * @return left regular grammar equivalent to source automaton. - */ - grammar::LeftRG convert(const automaton::NFA& automaton); + /** + * Performs conversion. + * @return left regular grammar equivalent to source automaton. + */ + static grammar::Grammar convert(const automaton::Automaton& automaton); + + static grammar::LeftRG convert(const automaton::NFA& automaton); + static grammar::LeftRG convert(const automaton::DFA& automaton); + +private: + void Visit(void*, const automaton::UnknownAutomaton& automaton) const; + void Visit(void*, const automaton::EpsilonNFA& 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::NPDA& automaton) const; + void Visit(void*, const automaton::SinglePopNPDA& automaton) const; + void Visit(void*, const automaton::OneTapeDTM& automaton) const; + + static const FAtoLRGConverter FA_TO_LRG_CONVERTER; }; } /* namespace fa2rg */ diff --git a/alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.cpp b/alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.cpp index 4cf3d3cf79d2084d3a3d0e3a9f4719ee2bb8455f..6c3a83fba75bfb593277ecf6573f07ffba4f15b7 100644 --- a/alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.cpp +++ b/alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.cpp @@ -1,53 +1,150 @@ #include "FAtoRRGConverter.h" +#include <label/StringLabel.h> #include <alphabet/LabeledSymbol.h> +#include <exception/AlibException.h> + namespace fa2rg { grammar::RightRG FAtoRRGConverter::convert(const automaton::NFA& automaton) { - std::map<automaton::State, alphabet::Symbol> nonterminalMap; + std::map<automaton::State, alphabet::Symbol> nonterminalMap; + + const automaton::State& initState = *automaton.getInitialStates().begin(); //FIXME what about other initial states + const alphabet::Symbol initSymbol(alphabet::LabeledSymbol(initState.getName())); + + grammar::RightRG grammar(initSymbol); + nonterminalMap.insert(std::make_pair(initState, initSymbol)); + + grammar.setTerminalAlphabet(automaton.getInputAlphabet()); + + for(const auto& state : automaton.getStates()) + { + if(state == initState) + continue; + + alphabet::Symbol nt = alphabet::createUniqueSymbol(alphabet::Symbol(alphabet::LabeledSymbol(state.getName())), grammar.getTerminalAlphabet(), grammar.getNonterminalAlphabet()); + grammar.addNonterminalSymbol(nt); + nonterminalMap.insert(std::make_pair(state, nt)); + } + + // step 2 - create set of P in G + for(const auto& transition : automaton.getTransitions()) + { + const automaton::State& from = transition.first.first; + const alphabet::Symbol& input = transition.first.second; + for(const auto& to : transition.second) + { + grammar.addRule(nonterminalMap.find(from)->second, std::make_pair(input, nonterminalMap.find(to)->second)); // 2a + if(automaton.getFinalStates().count(to)) // 2b + grammar.addRule(nonterminalMap.find(from)->second, input); + } + } + + // step 3 - set start symbol of G + grammar.setInitialSymbol(nonterminalMap.find(*automaton.getInitialStates().begin())->second); + + // step 4 + for(const auto & initial : automaton.getInitialStates()) { + if(automaton.getFinalStates().count(initial) > 0) + grammar.setGeneratesEpsilon(true); // okay this feature makes algorithm mismatch mathematical but simplifies the code actually :)) + } + + return grammar; +} + +grammar::RightRG FAtoRRGConverter::convert(const automaton::DFA& automaton) +{ + std::map<automaton::State, alphabet::Symbol> nonterminalMap; + + const automaton::State& initState = automaton.getInitialState(); + const alphabet::Symbol initSymbol(alphabet::LabeledSymbol(initState.getName())); - const automaton::State& initState = *automaton.getInitialStates().begin(); - const alphabet::Symbol initSymbol(alphabet::LabeledSymbol(initState.getName())); + grammar::RightRG grammar(initSymbol); + nonterminalMap.insert(std::make_pair(initState, initSymbol)); - grammar::RightRG grammar(initSymbol); - nonterminalMap.insert(std::make_pair(initState, initSymbol)); + grammar.setTerminalAlphabet(automaton.getInputAlphabet()); - grammar.setTerminalAlphabet(automaton.getInputAlphabet()); + for(const auto& state : automaton.getStates()) + { + if(state == initState) + continue; - for(const auto& state : automaton.getStates()) - { - if(state == initState) - continue; + alphabet::Symbol nt = alphabet::createUniqueSymbol(alphabet::Symbol(alphabet::LabeledSymbol(state.getName())), grammar.getTerminalAlphabet(), grammar.getNonterminalAlphabet()); + grammar.addNonterminalSymbol(nt); + nonterminalMap.insert(std::make_pair(state, nt)); + } - alphabet::Symbol nt = alphabet::createUniqueSymbol(alphabet::Symbol(alphabet::LabeledSymbol(state.getName())), grammar.getTerminalAlphabet(), grammar.getNonterminalAlphabet()); - grammar.addNonterminalSymbol(nt); - nonterminalMap.insert(std::make_pair(state, nt)); - } + // step 2 - create set of P in G + for(const auto& transition : automaton.getTransitions()) + { + const automaton::State& from = transition.first.first; + const alphabet::Symbol& input = transition.first.second; + const automaton::State& to = transition.second; - // step 2 - create set of P in G - for(const auto& transition : automaton.getTransitions()) - { - const automaton::State& from = transition.first.first; - const alphabet::Symbol& input = transition.first.second; - for(const auto& to : transition.second) - { - grammar.addRule(nonterminalMap.find(from)->second, std::make_pair(input, nonterminalMap.find(to)->second)); // 2a - if(automaton.getFinalStates().count(to)) // 2b - grammar.addRule(nonterminalMap.find(from)->second, input); - } - } + grammar.addRule(nonterminalMap.find(from)->second, std::make_pair(input, nonterminalMap.find(to)->second)); // 2a + if(automaton.getFinalStates().count(to)) // 2b + grammar.addRule(nonterminalMap.find(from)->second, input); + } - // step 3 - set start symbol of G - grammar.setInitialSymbol(nonterminalMap.find(*automaton.getInitialStates().begin())->second); + // step 3 - set start symbol of G + grammar.setInitialSymbol(nonterminalMap.find(automaton.getInitialState())->second); - // step 4 - if(automaton.getFinalStates().count(*automaton.getInitialStates().begin())) - grammar.setGeneratesEpsilon(true); // okay this feature breaks algorithm but simplifies the code actually :)) + // step 4 + if(automaton.getFinalStates().count(automaton.getInitialState())) + grammar.setGeneratesEpsilon(true); // okay this feature breaks algorithm but simplifies the code actually :)) + + return grammar; +} + +grammar::Grammar FAtoRRGConverter::convert(const automaton::Automaton& automaton) { + grammar::Grammar* out = NULL; + automaton.getData().Accept((void*) &out, FAtoRRGConverter::FA_TO_RRG_CONVERTER); + grammar::Grammar res = std::move(*out); + delete out; + return res; +} - return grammar; +void FAtoRRGConverter::Visit(void*, const automaton::UnknownAutomaton&) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); } +void FAtoRRGConverter::Visit(void*, const automaton::EpsilonNFA& ) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} + +void FAtoRRGConverter::Visit(void* data, const automaton::NFA& automaton) const { + grammar::Grammar* & out = *((grammar::Grammar**) data); + out = new grammar::Grammar(this->convert(automaton)); +} + +void FAtoRRGConverter::Visit(void* data, const automaton::DFA& automaton) const { + grammar::Grammar* & out = *((grammar::Grammar**) data); + out = new grammar::Grammar(this->convert(automaton)); +} + +void FAtoRRGConverter::Visit(void*, const automaton::ExtendedNFA& ) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} + +void FAtoRRGConverter::Visit(void*, const automaton::CompactNFA& ) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} + +void FAtoRRGConverter::Visit(void*, const automaton::NPDA&) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} + +void FAtoRRGConverter::Visit(void*, const automaton::SinglePopNPDA&) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} + +void FAtoRRGConverter::Visit(void*, const automaton::OneTapeDTM&) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} + +const FAtoRRGConverter FAtoRRGConverter::FA_TO_RRG_CONVERTER; + } /* namespace fa2rg */ diff --git a/alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.h b/alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.h index 79132db83956f40ff4c36bb88336d36ff7238121..bd6ee8fd14d5c642218531b8d3dea7a539f6a6d4 100644 --- a/alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.h +++ b/alib2algo/src/conversions/fa2rg/fa2rrg/FAtoRRGConverter.h @@ -3,6 +3,10 @@ #include <grammar/Regular/RightRG.h> #include <automaton/FSM/NFA.h> +#include <automaton/FSM/DFA.h> + +#include <grammar/Grammar.h> +#include <automaton/Automaton.h> namespace fa2rg { @@ -11,17 +15,30 @@ namespace fa2rg * Finite automaton to right regular grammar converter. * Source: Melichar 2.104 */ -class FAtoRRGConverter +class FAtoRRGConverter : public automaton::VisitableAutomatonBase::const_visitor_type { public: - /** - * Performs conversion. - * @return left regular grammar equivalent to source automaton. - */ - grammar::RightRG convert(const automaton::NFA& automaton); + /** + * Performs conversion. + * @return left regular grammar equivalent to source automaton. + */ + static grammar::Grammar convert(const automaton::Automaton& automaton); + + static grammar::RightRG convert(const automaton::NFA& automaton); + static grammar::RightRG convert(const automaton::DFA& automaton); private: - bool isSymbolOnAnyRightHandSide(const alphabet::Symbol& symbol, const grammar::RightRG& grammar) const; + void Visit(void*, const automaton::UnknownAutomaton& automaton) const; + void Visit(void*, const automaton::EpsilonNFA& 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::NPDA& automaton) const; + void Visit(void*, const automaton::SinglePopNPDA& automaton) const; + void Visit(void*, const automaton::OneTapeDTM& automaton) const; + + static const FAtoRRGConverter FA_TO_RRG_CONVERTER; }; } /* namespace fa2rg */