diff --git a/aepsilon2/src/aepsilon.cpp b/aepsilon2/src/aepsilon.cpp index 3c8cf8f8c712958a522135bf9a4377c7f1875c3d..2baf53dc82a8e98287a078c6d89316368a4db80d 100644 --- a/aepsilon2/src/aepsilon.cpp +++ b/aepsilon2/src/aepsilon.cpp @@ -3,7 +3,6 @@ // Author : Tomas Pecka //============================================================================ - #include <iostream> #include <factory/DataFactory.hpp> @@ -12,50 +11,26 @@ #include "epsilon/fsm/FSMEpsilonRemover.h" int main(int argc, char** argv) { - int fileParameterIndex = -1; try { - if( argc > 1 ) - { - for( int i = 1; i < argc; i++ ) - { - if( std::string( "-h" ).compare( argv[i] ) == 0 ) - { - std::cout << "Removes eps transitions from NFA." << std::endl; - std::cout << "Usage: aepsilon [automaton.xml]" << std::endl; - return 1; - } - else - { - if(fileParameterIndex == -1) - fileParameterIndex = i; - else - throw exception::AlibException("Only one file can be passed as parameter - " + std::string(argv[i]) + " " + std::string(argv[fileParameterIndex])); - } - } - } - - std::list<sax::Token> tokens; - - if(fileParameterIndex != -1) { - sax::SaxParseInterface::parseFile(argv[fileParameterIndex], tokens); + if (argc == 2 && std::string("-h").compare(argv[1]) == 0) { + std::cout << "Remove epsilon transitions from automaton." << std::endl << "Usage: aepsilon [automaton.xml]" << std::endl; + return -1; + } else if (argc == 1 || (argc == 2 && std::string("--").compare(argv[1]) == 0)) { + alib::DataFactory::toStdout(epsilon::FSMEpsilonRemover::remove(alib::DataFactory::fromStdin<automaton::Automaton>())); + } else if (argc == 2) { + alib::DataFactory::toStdout(epsilon::FSMEpsilonRemover::remove(alib::DataFactory::fromStdin<automaton::Automaton>())); } else { - sax::SaxParseInterface::parseStdin(tokens); + std::cout << "Automaton minimize require deterministic finite automaton" << std::endl; + return 1; } - if(alib::FromXMLParsers::automatonParser.first(tokens)) { - std::string xmlMark = tokens.front( ).getData( ); - automaton::Automaton automaton = alib::DataFactory::fromTokens<automaton::Automaton>(tokens); - automaton::Automaton res = epsilon::FSMEpsilonRemover::remove( automaton ); - alib::DataFactory::toStdout(res); - } else { - throw exception::AlibException("Invalid argument expected Epsilon NFA."); - } + return 0; } catch (const exception::AlibException& exception) { alib::DataFactory::toStdout(exception); return 1; - } catch (...) { + } catch(...) { return 127; } } diff --git a/alib2algo/src/conversions/fa2re/Algebraic.cpp b/alib2algo/src/conversions/fa2re/Algebraic.cpp index 16f1492fb36c7a8c1a347eb2b9c649f6ff7ee834..44d14dc7c69e63e74fad45aa25770bf6bac580b0 100644 --- a/alib2algo/src/conversions/fa2re/Algebraic.cpp +++ b/alib2algo/src/conversions/fa2re/Algebraic.cpp @@ -6,16 +6,28 @@ */ #include "Algebraic.h" -#include "alphabet/Symbol.h" -#include "automaton/FSM/DFA.h" -#include "automaton/FSM/NFA.h" -#include "automaton/FSM/EpsilonNFA.h" + +#include <alphabet/Symbol.h> +#include <automaton/FSM/DFA.h> +#include <automaton/FSM/NFA.h> +#include <automaton/FSM/EpsilonNFA.h> +#include <exception/AlibException.h> + +#include "../../equations/RightRegularEquationSolver.h" namespace conversions { namespace fa2re { +regexp::RegExp Algebraic::convert(const automaton::Automaton& automaton) { + regexp::RegExp* out = NULL; + automaton.getData().Accept((void*) &out, Algebraic::ALGEBRAIC); + regexp::RegExp res = std::move(*out); + delete out; + return res; +} + template<> regexp::UnboundedRegExp Algebraic::convert( const automaton::EpsilonNFA & automaton ) { equations::RightRegularEquationSolver solver; @@ -25,7 +37,7 @@ regexp::UnboundedRegExp Algebraic::convert( const automaton::EpsilonNFA & automa solver.addSymbol( alphabet::Symbol( alphabet::LabeledSymbol( q.getName( ) ) ) ); for( const auto & q : automaton.getStates( ) ) { - if( isInSet( q, automaton.getFinalStates( ) ) ) + if( automaton.getFinalStates( ).count( q ) > 0 ) solver.addEquation( alphabet::Symbol( alphabet::LabeledSymbol ( q.getName( ) ) ), regexp::UnboundedRegExpEpsilon { } ); } @@ -61,7 +73,7 @@ regexp::UnboundedRegExp Algebraic::convert( const automaton::NFA & automaton ) { solver.addSymbol( alphabet::Symbol( alphabet::LabeledSymbol( q.getName( ) ) ) ); for( const auto & q : automaton.getStates( ) ) { - if( isInSet( q, automaton.getFinalStates( ) ) ) + if( automaton.getFinalStates( ).count( q ) > 0 ) solver.addEquation( alphabet::Symbol( alphabet::LabeledSymbol ( q.getName( ) ) ), regexp::UnboundedRegExpEpsilon { } ); } @@ -91,7 +103,7 @@ regexp::UnboundedRegExp Algebraic::convert( const automaton::DFA & automaton ) { solver.addSymbol( alphabet::Symbol( alphabet::LabeledSymbol( q.getName( ) ) ) ); for( const auto & q : automaton.getStates( ) ) { - if( isInSet( q, automaton.getFinalStates( ) ) ) + if( automaton.getFinalStates( ).count( q ) > 0 ) solver.addEquation( alphabet::Symbol( alphabet::LabeledSymbol ( q.getName( ) ) ), regexp::UnboundedRegExpEpsilon { } ); } @@ -102,6 +114,64 @@ regexp::UnboundedRegExp Algebraic::convert( const automaton::DFA & automaton ) { return solver.solve( alphabet::Symbol( alphabet::LabeledSymbol (automaton.getInitialState().getName() ) ) ); } + +void Algebraic::Visit(void*, const automaton::UnknownAutomaton&) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} + +void Algebraic::Visit(void* data, const automaton::EpsilonNFA& automaton) const { + regexp::RegExp* & out = *((regexp::RegExp**) data); + out = new regexp::RegExp(this->convert(automaton)); +} + +void Algebraic::Visit(void* data, const automaton::NFA& automaton) const { + regexp::RegExp* & out = *((regexp::RegExp**) data); + out = new regexp::RegExp(this->convert(automaton)); +} + +void Algebraic::Visit(void* data, const automaton::DFA& automaton) const { + regexp::RegExp* & out = *((regexp::RegExp**) data); + out = new regexp::RegExp(this->convert(automaton)); +} + +void Algebraic::Visit(void*, const automaton::ExtendedNFA& ) const { + throw exception::AlibException("Unsupported automaton type ExtendedNFA"); +} + +void Algebraic::Visit(void*, const automaton::CompactNFA& ) const { + throw exception::AlibException("Unsupported automaton type CompactNFA"); +} + +void Algebraic::Visit(void*, const automaton::DPDA&) const { + throw exception::AlibException("Unsupported automaton type DPDA"); +} + +void Algebraic::Visit(void*, const automaton::SinglePopDPDA&) const { + throw exception::AlibException("Unsupported automaton type SinglePopDPDA"); +} + +void Algebraic::Visit(void*, const automaton::InputDrivenNPDA&) const { + throw exception::AlibException("Unsupported automaton type InputDrivenNPDA"); +} + +void Algebraic::Visit(void*, const automaton::VisiblyPushdownNPDA&) const { + throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA"); +} + +void Algebraic::Visit(void*, const automaton::NPDA&) const { + throw exception::AlibException("Unsupported automaton type NPDA"); +} + +void Algebraic::Visit(void*, const automaton::SinglePopNPDA&) const { + throw exception::AlibException("Unsupported automaton type SinglePopNPDA"); +} + +void Algebraic::Visit(void*, const automaton::OneTapeDTM&) const { + throw exception::AlibException("Unsupported automaton type OneTapeDTM"); +} + +const Algebraic Algebraic::ALGEBRAIC; + } /* namespace fa2re */ } /* namespace conversions */ diff --git a/alib2algo/src/conversions/fa2re/Algebraic.h b/alib2algo/src/conversions/fa2re/Algebraic.h index 55dbaca7def75373f427aad929e7552d0c72e7ac..a6fbc2471e778d656a4e266cb63ef641391a45bd 100644 --- a/alib2algo/src/conversions/fa2re/Algebraic.h +++ b/alib2algo/src/conversions/fa2re/Algebraic.h @@ -12,10 +12,9 @@ #include <map> #include <queue> +#include <regexp/RegExp.h> #include <regexp/unbounded/UnboundedRegExpElements.h> - -#include "common/macros.h" -#include "../../equations/RightRegularEquationSolver.h" +#include <automaton/Automaton.h> namespace conversions { @@ -30,15 +29,34 @@ namespace fa2re * Converts FA to RE using Brzozowski's algebraic method using right regular equations. * Source : Melichar 2.122 */ -class Algebraic +class Algebraic : public automaton::VisitableAutomatonBase::const_visitor_type { public: /** * Performs conversion. * @return regular expression equivalent to input automaton. */ + static regexp::RegExp convert(const automaton::Automaton& automaton); + template <class T> - static regexp::UnboundedRegExp convert( const T & automaton ); + static regexp::UnboundedRegExp convert(const T& automaton); + +private: + void Visit(void*, const automaton::UnknownAutomaton&) const; + void Visit(void*, const automaton::EpsilonNFA&) const; + void Visit(void*, const automaton::NFA&) const; + void Visit(void*, const automaton::DFA&) const; + void Visit(void*, const automaton::ExtendedNFA&) const; + void Visit(void*, const automaton::CompactNFA&) const; + void Visit(void*, const automaton::InputDrivenNPDA&) const; + void Visit(void*, const automaton::VisiblyPushdownNPDA&) const; + void Visit(void*, const automaton::NPDA&) const; + void Visit(void*, const automaton::SinglePopNPDA&) const; + void Visit(void*, const automaton::DPDA&) const; + void Visit(void*, const automaton::SinglePopDPDA&) const; + void Visit(void*, const automaton::OneTapeDTM&) const; + + static const Algebraic ALGEBRAIC; }; } /* namespace fa2re */ diff --git a/alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.cpp b/alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.cpp index 12e09fae7de98de43b1a6db0ea9af252b2cb8480..b1d2316e4adea49b46b6ec4a95f3b52318d70e06 100644 --- a/alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.cpp +++ b/alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.cpp @@ -19,11 +19,20 @@ namespace conversions namespace fa2re { +regexp::RegExp StateEliminationFormal::convert(const automaton::Automaton& automaton) +{ + regexp::RegExp* out = NULL; + automaton.getData().Accept((void*) &out, StateEliminationFormal::STATE_ELIMINATION_FORMAL); + regexp::RegExp res = std::move(*out); + delete out; + return res; +} + template<class T> -regexp::RegExp StateEliminationFormal::convert(const T& automaton) +regexp::FormalRegExp StateEliminationFormal::convert(const T& automaton) { if(automaton.getFinalStates().size() == 0) - return regexp::RegExp{regexp::FormalRegExp(regexp::FormalRegExpEmpty())}; + return regexp::FormalRegExp(regexp::FormalRegExpEmpty()); // steps 1 + 2 automaton::ExtendedNFA extendedAutomaton = constructExtendedNFA(automaton); @@ -46,21 +55,10 @@ regexp::RegExp StateEliminationFormal::convert(const T& automaton) regexp::FormalRegExpIteration(std::move(*transition(extendedAutomaton, *extendedAutomaton.getFinalStates().begin(), *extendedAutomaton.getFinalStates().begin()))) ); //return regexp::RegExp{opt.optimize(regexp::FormalRegExp(concat))}; - return regexp::RegExp{regexp::FormalRegExp(concat)}; -} - -template<> -regexp::RegExp StateEliminationFormal::convert(const automaton::Automaton& automaton) -{ - regexp::RegExp* out = NULL; - automaton.getData().Accept((void*) &out, StateEliminationFormal::STATE_ELIMINATION_FORMAL); - regexp::RegExp res = std::move(*out); - delete out; - return res; + return regexp::FormalRegExp(concat); } - void StateEliminationFormal::Visit(void*, const automaton::UnknownAutomaton&) const { throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); diff --git a/alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.h b/alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.h index d94d57d849658b452b691585402543842452e460..e71cce1a267ffecb9bac14dd45e23a2e6f60a35f 100644 --- a/alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.h +++ b/alib2algo/src/conversions/fa2re/formal/StateEliminationFormal.h @@ -34,8 +34,10 @@ public: * Performs conversion. * @return regular expression equivalent to source NFA. */ + static regexp::RegExp convert(const automaton::Automaton& automaton); + template<class T> - static regexp::RegExp convert(const T& automaton); + static regexp::FormalRegExp convert(const T& automaton); private: void Visit(void*, const automaton::UnknownAutomaton& automaton) const; diff --git a/alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.cpp b/alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.cpp index dd4422ec1ec9934326fa87afdd5a11ac18ad65e1..b714edfa725e40c60fa53c3f9054e4db86ed5d10 100644 --- a/alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.cpp +++ b/alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.cpp @@ -19,11 +19,20 @@ namespace conversions namespace fa2re { +regexp::RegExp StateEliminationUnbounded::convert(const automaton::Automaton& automaton) +{ + regexp::RegExp* out = NULL; + automaton.getData().Accept((void*) &out, StateEliminationUnbounded::STATE_ELIMINATION_UNBOUNDED); + regexp::RegExp res = std::move(*out); + delete out; + return res; +} + template<class T> -regexp::RegExp StateEliminationUnbounded::convert(const T& automaton) +regexp::UnboundedRegExp StateEliminationUnbounded::convert(const T& automaton) { if(automaton.getFinalStates().size() == 0) - return regexp::RegExp{regexp::UnboundedRegExp(regexp::UnboundedRegExpEmpty())}; + return regexp::UnboundedRegExp(regexp::UnboundedRegExpEmpty()); // steps 1 + 2 automaton::ExtendedNFA extendedAutomaton = constructExtendedNFA(automaton); @@ -44,21 +53,10 @@ regexp::RegExp StateEliminationUnbounded::convert(const T& automaton) regexp::UnboundedRegExpConcatenation concat; concat.appendElement(std::move(*transition(extendedAutomaton, *extendedAutomaton.getInitialStates().begin(), *extendedAutomaton.getFinalStates().begin()))); concat.appendElement(regexp::UnboundedRegExpIteration(std::move(*transition(extendedAutomaton, *extendedAutomaton.getFinalStates().begin(), *extendedAutomaton.getFinalStates().begin())))); - return regexp::RegExp{opt.optimize(regexp::UnboundedRegExp(concat))}; -} - -template<> -regexp::RegExp StateEliminationUnbounded::convert(const automaton::Automaton& automaton) -{ - regexp::RegExp* out = NULL; - automaton.getData().Accept((void*) &out, StateEliminationUnbounded::STATE_ELIMINATION_UNBOUNDED); - regexp::RegExp res = std::move(*out); - delete out; - return res; + return opt.optimize(regexp::UnboundedRegExp(concat)); } - void StateEliminationUnbounded::Visit(void*, const automaton::UnknownAutomaton&) const { throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); diff --git a/alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.h b/alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.h index 5cbd9c8840bd2a983d2bb74dba101ccbd09e7035..fa6c114a17e970ac2c9f2346b81799536eeac9b8 100644 --- a/alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.h +++ b/alib2algo/src/conversions/fa2re/unbounded/StateEliminationUnbounded.h @@ -32,10 +32,13 @@ class StateEliminationUnbounded : public automaton::VisitableAutomatonBase::cons public: /** * Performs conversion. + * @param automaton automaton to convert * @return regular expression equivalent to source NFA. */ + static regexp::RegExp convert(const automaton::Automaton& automaton); + template<class T> - static regexp::RegExp convert(const T& automaton); + static regexp::UnboundedRegExp convert(const T& automaton); private: void Visit(void*, const automaton::UnknownAutomaton& automaton) const; diff --git a/alib2algo/src/conversions/re2fa/Thompson.cpp b/alib2algo/src/conversions/re2fa/Thompson.cpp index 092f08422bca7f81f5307295558d739aeb3f46b9..e61a87b637614a452c0a5effda3e9b5afcc6e943 100644 --- a/alib2algo/src/conversions/re2fa/Thompson.cpp +++ b/alib2algo/src/conversions/re2fa/Thompson.cpp @@ -13,11 +13,11 @@ namespace conversions namespace re2fa { -automaton::EpsilonNFA Thompson::convert(const regexp::RegExp& regexp) +automaton::Automaton Thompson::convert(const regexp::RegExp& regexp) { - automaton::EpsilonNFA* out = NULL; + automaton::Automaton* out = NULL; regexp.getData().Accept((void*) &out, Thompson::THOMPSON); - automaton::EpsilonNFA res = std::move(*out); + automaton::Automaton res = std::move(*out); delete out; return res; } @@ -42,14 +42,14 @@ automaton::EpsilonNFA Thompson::convert(const T& regexp) void Thompson::Visit(void* userData, const regexp::FormalRegExp& regexp) const { - automaton::EpsilonNFA* & out = *((automaton::EpsilonNFA**) userData); - out = new automaton::EpsilonNFA(this->convert(regexp)); + automaton::Automaton* & out = *((automaton::Automaton**) userData); + out = new automaton::Automaton(this->convert(regexp)); } void Thompson::Visit(void* userData, const regexp::UnboundedRegExp& regexp) const { - automaton::EpsilonNFA* & out = *((automaton::EpsilonNFA**) userData); - out = new automaton::EpsilonNFA(this->convert(regexp)); + automaton::Automaton* & out = *((automaton::Automaton**) userData); + out = new automaton::Automaton(this->convert(regexp)); } // ---------------------------------------------------------------------------- diff --git a/alib2algo/src/conversions/re2fa/Thompson.h b/alib2algo/src/conversions/re2fa/Thompson.h index d3365ec0b9361485831ea03101ad96bc09f416d5..e127f07f54e53f48e9691986e9f04e6d0af0f312 100644 --- a/alib2algo/src/conversions/re2fa/Thompson.h +++ b/alib2algo/src/conversions/re2fa/Thompson.h @@ -11,6 +11,7 @@ #include <regexp/RegExp.h> #include <regexp/formal/FormalRegExpElements.h> #include <regexp/unbounded/UnboundedRegExpElements.h> +#include <automaton/Automaton.h> #include <automaton/FSM/EpsilonNFA.h> namespace conversions @@ -35,7 +36,7 @@ public: * @param regexp regexp to convert * @return nondeterministic finite automaton with epsilon transitions accepting language described by the regexp */ - static automaton::EpsilonNFA convert(const regexp::RegExp& regexp); + static automaton::Automaton convert(const regexp::RegExp& regexp); template<class T> static automaton::EpsilonNFA convert(const T& regexp); diff --git a/alib2algo/src/determinize/nfa/NFADeterminizer.cpp b/alib2algo/src/determinize/nfa/NFADeterminizer.cpp index 9af97b5284203cb2908e7ac182fb58c2e93a72e9..c95aae328fe05a9880d462fdb8516bf9b9f31caa 100644 --- a/alib2algo/src/determinize/nfa/NFADeterminizer.cpp +++ b/alib2algo/src/determinize/nfa/NFADeterminizer.cpp @@ -13,6 +13,13 @@ namespace determinize { +automaton::Automaton NFADeterminizer::determinize(const automaton::Automaton& automaton) { + automaton::Automaton* out = NULL; + automaton.getData().Accept((void*) &out, NFADeterminizer::NFA_DETERMINIZER); + automaton::Automaton res = std::move(*out); + delete out; + return res; +} automaton::State NFADeterminizer::createDFAState(const std::set<automaton::State>& nfaStates) { std::set<label::Label> labelSet; @@ -77,4 +84,59 @@ automaton::DFA NFADeterminizer::determinize(const automaton::NFA& nfa) { return res; } +void NFADeterminizer::Visit(void*, const automaton::UnknownAutomaton&) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} + +void NFADeterminizer::Visit(void*, const automaton::EpsilonNFA&) const { + throw exception::AlibException("Unsupported automaton type EpsilonNFA"); +} + +void NFADeterminizer::Visit(void* data, const automaton::NFA& automaton) const { + automaton::Automaton* & out = *((automaton::Automaton**) data); + out = new automaton::Automaton(this->determinize(automaton)); +} + +void NFADeterminizer::Visit(void*, const automaton::DFA&) const { + throw exception::AlibException("Unsupported automaton type DFA"); +} + +void NFADeterminizer::Visit(void*, const automaton::ExtendedNFA& ) const { + throw exception::AlibException("Unsupported automaton type ExtendedNFA"); +} + +void NFADeterminizer::Visit(void*, const automaton::CompactNFA& ) const { + throw exception::AlibException("Unsupported automaton type CompactNFA"); +} + +void NFADeterminizer::Visit(void*, const automaton::DPDA&) const { + throw exception::AlibException("Unsupported automaton type DPDA"); +} + +void NFADeterminizer::Visit(void*, const automaton::SinglePopDPDA&) const { + throw exception::AlibException("Unsupported automaton type SinglePopDPDA"); +} + +void NFADeterminizer::Visit(void*, const automaton::InputDrivenNPDA&) const { + throw exception::AlibException("Unsupported automaton type InputDrivenNPDA"); +} + +void NFADeterminizer::Visit(void*, const automaton::VisiblyPushdownNPDA&) const { + throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA"); +} + +void NFADeterminizer::Visit(void*, const automaton::NPDA&) const { + throw exception::AlibException("Unsupported automaton type NPDA"); +} + +void NFADeterminizer::Visit(void*, const automaton::SinglePopNPDA&) const { + throw exception::AlibException("Unsupported automaton type SinglePopNPDA"); +} + +void NFADeterminizer::Visit(void*, const automaton::OneTapeDTM&) const { + throw exception::AlibException("Unsupported automaton type OneTapeDTM"); +} + +const NFADeterminizer NFADeterminizer::NFA_DETERMINIZER; + } diff --git a/alib2algo/src/determinize/nfa/NFADeterminizer.h b/alib2algo/src/determinize/nfa/NFADeterminizer.h index b0a7697fa009ed4d57911cc481aa8afabe286ddd..b5476588710876243a50e7708970eb9958124b9a 100644 --- a/alib2algo/src/determinize/nfa/NFADeterminizer.h +++ b/alib2algo/src/determinize/nfa/NFADeterminizer.h @@ -10,16 +10,19 @@ #include <set> -#include "automaton/common/State.h" -#include "automaton/FSM/NFA.h" -#include "automaton/FSM/DFA.h" +#include <automaton/common/State.h> +#include <automaton/Automaton.h> +#include <automaton/FSM/NFA.h> +#include <automaton/FSM/DFA.h> + +#include <exception/AlibException.h> namespace determinize { /** * Class for running determinization algorithm on fsm. */ -class NFADeterminizer { +class NFADeterminizer : public automaton::VisitableAutomatonBase::const_visitor_type { private: @@ -41,14 +44,33 @@ private: * @return set of states from nondeterministic fsm */ static std::set<automaton::State> recreateNFAStates(const automaton::State& dfaState); + + 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::DPDA& automaton) const; + void Visit(void*, const automaton::SinglePopDPDA& automaton) const; + void Visit(void*, const automaton::InputDrivenNPDA& automaton) const; + void Visit(void*, const automaton::VisiblyPushdownNPDA& 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 NFADeterminizer NFA_DETERMINIZER; + public: /** * @param nfsm nondeterministic final-state machine given for determinization + * @return DFA * Runs determinization algorithm on nondeterministic fsm given in constructor. */ - static automaton::DFA determinize(const automaton::NFA& nfa); + static automaton::Automaton determinize(const automaton::Automaton& nfa); + static automaton::DFA determinize(const automaton::NFA& nfa); }; } /* namespace determinize */ diff --git a/alib2algo/src/minimize/dfa/MinimizeDFA.cpp b/alib2algo/src/minimize/dfa/MinimizeDFA.cpp index 9840a5e8c94fbd3e9ccb5ded0975c6fac726c17b..9eefeb1c975afa487773aa948c076aab0740fcfc 100644 --- a/alib2algo/src/minimize/dfa/MinimizeDFA.cpp +++ b/alib2algo/src/minimize/dfa/MinimizeDFA.cpp @@ -12,13 +12,23 @@ #include <sstream> #include <iostream> -#include "alphabet/Symbol.h" -#include "label/IntegerLabel.h" +#include <alphabet/Symbol.h> +#include <label/IntegerLabel.h> -#include "automaton/Automaton.h" +#include <exception/AlibException.h> + +#include <automaton/Automaton.h> namespace minimize { +automaton::Automaton MinimizeDFA::minimize(const automaton::Automaton& automaton) { + automaton::Automaton* out = NULL; + automaton.getData().Accept((void*) &out, MinimizeDFA::MINIMIZE_DFA); + automaton::Automaton res = std::move(*out); + delete out; + return res; +} + automaton::DFA MinimizeDFA::minimize(const automaton::DFA& dfa) { if(dfa.getFinalStates().size() == 0) { automaton::DFA result(automaton::State(0)); @@ -131,4 +141,59 @@ automaton::DFA MinimizeDFA::minimize(const automaton::DFA& dfa) { return result; } +void MinimizeDFA::Visit(void*, const automaton::UnknownAutomaton&) const { + throw exception::AlibException("Unsupported automaton type UnknownAutomaton"); +} + +void MinimizeDFA::Visit(void*, const automaton::EpsilonNFA&) const { + throw exception::AlibException("Unsupported automaton type EpsilonNFA"); +} + +void MinimizeDFA::Visit(void* data, const automaton::DFA& automaton) const { + automaton::Automaton* & out = *((automaton::Automaton**) data); + out = new automaton::Automaton(this->minimize(automaton)); +} + +void MinimizeDFA::Visit(void*, const automaton::NFA&) const { + throw exception::AlibException("Unsupported automaton type DFA"); +} + +void MinimizeDFA::Visit(void*, const automaton::ExtendedNFA& ) const { + throw exception::AlibException("Unsupported automaton type ExtendedNFA"); +} + +void MinimizeDFA::Visit(void*, const automaton::CompactNFA& ) const { + throw exception::AlibException("Unsupported automaton type CompactNFA"); +} + +void MinimizeDFA::Visit(void*, const automaton::DPDA&) const { + throw exception::AlibException("Unsupported automaton type DPDA"); +} + +void MinimizeDFA::Visit(void*, const automaton::SinglePopDPDA&) const { + throw exception::AlibException("Unsupported automaton type SinglePopDPDA"); +} + +void MinimizeDFA::Visit(void*, const automaton::InputDrivenNPDA&) const { + throw exception::AlibException("Unsupported automaton type InputDrivenNPDA"); +} + +void MinimizeDFA::Visit(void*, const automaton::VisiblyPushdownNPDA&) const { + throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA"); +} + +void MinimizeDFA::Visit(void*, const automaton::NPDA&) const { + throw exception::AlibException("Unsupported automaton type NPDA"); +} + +void MinimizeDFA::Visit(void*, const automaton::SinglePopNPDA&) const { + throw exception::AlibException("Unsupported automaton type SinglePopNPDA"); +} + +void MinimizeDFA::Visit(void*, const automaton::OneTapeDTM&) const { + throw exception::AlibException("Unsupported automaton type OneTapeDTM"); +} + +const MinimizeDFA MinimizeDFA::MINIMIZE_DFA; + } /* namespace minimize */ diff --git a/alib2algo/src/minimize/dfa/MinimizeDFA.h b/alib2algo/src/minimize/dfa/MinimizeDFA.h index 056914756a99a3c9aa4cae6c487df17ed8a88128..ea20405e8ab17e34c91a20c6740e309f44cd2549 100644 --- a/alib2algo/src/minimize/dfa/MinimizeDFA.h +++ b/alib2algo/src/minimize/dfa/MinimizeDFA.h @@ -8,14 +8,36 @@ #ifndef MINIMIZE_DFA_H_ #define MINIMIZE_DFA_H_ -#include "automaton/FSM/DFA.h" +#include <automaton/Automaton.h> +#include <automaton/FSM/DFA.h> namespace minimize { -class MinimizeDFA { +class MinimizeDFA : public automaton::VisitableAutomatonBase::const_visitor_type { public: + /** + * @param dfa automaton to minimize + */ + static automaton::Automaton minimize(const automaton::Automaton& dfa); + static automaton::DFA minimize(const automaton::DFA& dfa); +protected: + 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::DPDA& automaton) const; + void Visit(void*, const automaton::SinglePopDPDA& automaton) const; + void Visit(void*, const automaton::InputDrivenNPDA& automaton) const; + void Visit(void*, const automaton::VisiblyPushdownNPDA& 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 MinimizeDFA MINIMIZE_DFA; }; } diff --git a/alib2algo/test-src/conversions/re2fa/re2faTest.cpp b/alib2algo/test-src/conversions/re2fa/re2faTest.cpp index 4806de5eb3591f0f92beeb2f5de3ff19ed3767c4..9adb79a4c57b375ed7e1360c009cec27ed8b8a02 100644 --- a/alib2algo/test-src/conversions/re2fa/re2faTest.cpp +++ b/alib2algo/test-src/conversions/re2fa/re2faTest.cpp @@ -31,22 +31,20 @@ void re2faTest::testThompson() { regexp::RegExpFromStringParser parser(inputs); regexp::RegExp regexp1( parser.parseValue() ); - conversions::re2fa::Thompson thompson1; - automaton::EpsilonNFA enfa1 = thompson1.convert(regexp1); + automaton::Automaton enfa1 = conversions::re2fa::Thompson::convert(regexp1); regexp::RegExp regexp2( conversions::fa2re::Algebraic::convert(enfa1) ); - conversions::re2fa::Thompson thompson2; - automaton::EpsilonNFA enfa2 = thompson2.convert(regexp2); + automaton::Automaton enfa2 = conversions::re2fa::Thompson::convert(regexp2); - automaton::NFA nfa1 = epsilon::FSMEpsilonRemover::remove(enfa1); - automaton::NFA nfa2 = epsilon::FSMEpsilonRemover::remove(enfa2); + automaton::Automaton nfa1 = epsilon::FSMEpsilonRemover::remove(enfa1); + automaton::Automaton nfa2 = epsilon::FSMEpsilonRemover::remove(enfa2); - automaton::DFA dfa1 = determinize::NFADeterminizer::determinize(nfa1); - automaton::DFA dfa2 = determinize::NFADeterminizer::determinize(nfa2); + automaton::Automaton dfa1 = determinize::NFADeterminizer::determinize(nfa1); + automaton::Automaton dfa2 = determinize::NFADeterminizer::determinize(nfa2); - automaton::DFA mdfa1 = minimize::MinimizeDFA::minimize(dfa1); - automaton::DFA mdfa2 = minimize::MinimizeDFA::minimize(dfa2); + automaton::Automaton mdfa1 = minimize::MinimizeDFA::minimize(dfa1); + automaton::Automaton mdfa2 = minimize::MinimizeDFA::minimize(dfa2); CPPUNIT_ASSERT( mdfa1 == mdfa2); } diff --git a/aminimize2/src/aminimize.cpp b/aminimize2/src/aminimize.cpp index d43b6430c060664998ef0b821d742cff16d2a7c2..b2c963e5e4ba9d0055b2da791c8ed2b4b87a1719 100644 --- a/aminimize2/src/aminimize.cpp +++ b/aminimize2/src/aminimize.cpp @@ -4,35 +4,26 @@ //============================================================================ #include <iostream> -#include <string> -#include <set> -#include "exception/AlibException.h" -#include "factory/DataFactory.hpp" +#include <exception/AlibException.h> +#include <factory/DataFactory.hpp> + #include "minimize/dfa/MinimizeDFA.h" int main(int argc, char** argv) { try { - - automaton::DFA* automatonPointer = NULL; - if (argc == 2 && std::string("-h").compare(argv[1]) == 0) { std::cout << "Automaton minimize." << std::endl << "Usage: aminimize 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(minimize::MinimizeDFA::minimize(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(minimize::MinimizeDFA::minimize(alib::DataFactory::fromStdin<automaton::Automaton>())); } else { std::cout << "Automaton minimize require deterministic finite automaton" << std::endl; return 1; } - - automaton::DFA res = minimize::MinimizeDFA::minimize(*automatonPointer); - alib::DataFactory::toStdout(res); - - delete automatonPointer; return 0;