Skip to content
Snippets Groups Projects
Commit a8f6ad75 authored by Tomáš Pecka's avatar Tomáš Pecka
Browse files

algo: API for re2fa::Thompson, NFA Determinize, DFA minimize

parent 96951612
No related branches found
No related tags found
No related merge requests found
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
// Author : Tomas Pecka // Author : Tomas Pecka
//============================================================================ //============================================================================
   
#include <iostream> #include <iostream>
   
#include <factory/DataFactory.hpp> #include <factory/DataFactory.hpp>
...@@ -12,50 +11,26 @@ ...@@ -12,50 +11,26 @@
#include "epsilon/fsm/FSMEpsilonRemover.h" #include "epsilon/fsm/FSMEpsilonRemover.h"
   
int main(int argc, char** argv) { int main(int argc, char** argv) {
int fileParameterIndex = -1;
   
try { try {
if( argc > 1 ) 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;
for( int i = 1; i < argc; i++ ) return -1;
{ } else if (argc == 1 || (argc == 2 && std::string("--").compare(argv[1]) == 0)) {
if( std::string( "-h" ).compare( argv[i] ) == 0 ) alib::DataFactory::toStdout(epsilon::FSMEpsilonRemover::remove(alib::DataFactory::fromStdin<automaton::Automaton>()));
{ } else if (argc == 2) {
std::cout << "Removes eps transitions from NFA." << std::endl; alib::DataFactory::toStdout(epsilon::FSMEpsilonRemover::remove(alib::DataFactory::fromStdin<automaton::Automaton>()));
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);
} else { } else {
sax::SaxParseInterface::parseStdin(tokens); std::cout << "Automaton minimize require deterministic finite automaton" << std::endl;
return 1;
} }
   
if(alib::FromXMLParsers::automatonParser.first(tokens)) { return 0;
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.");
}
   
} catch (const exception::AlibException& exception) { } catch (const exception::AlibException& exception) {
alib::DataFactory::toStdout(exception); alib::DataFactory::toStdout(exception);
return 1; return 1;
} catch (...) { } catch(...) {
return 127; return 127;
} }
} }
...@@ -13,11 +13,11 @@ namespace conversions ...@@ -13,11 +13,11 @@ namespace conversions
namespace re2fa 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); regexp.getData().Accept((void*) &out, Thompson::THOMPSON);
automaton::EpsilonNFA res = std::move(*out); automaton::Automaton res = std::move(*out);
delete out; delete out;
return res; return res;
} }
...@@ -42,14 +42,14 @@ automaton::EpsilonNFA Thompson::convert(const T& regexp) ...@@ -42,14 +42,14 @@ automaton::EpsilonNFA Thompson::convert(const T& regexp)
   
void Thompson::Visit(void* userData, const regexp::FormalRegExp& regexp) const void Thompson::Visit(void* userData, const regexp::FormalRegExp& regexp) const
{ {
automaton::EpsilonNFA* & out = *((automaton::EpsilonNFA**) userData); automaton::Automaton* & out = *((automaton::Automaton**) userData);
out = new automaton::EpsilonNFA(this->convert(regexp)); out = new automaton::Automaton(this->convert(regexp));
} }
   
void Thompson::Visit(void* userData, const regexp::UnboundedRegExp& regexp) const void Thompson::Visit(void* userData, const regexp::UnboundedRegExp& regexp) const
{ {
automaton::EpsilonNFA* & out = *((automaton::EpsilonNFA**) userData); automaton::Automaton* & out = *((automaton::Automaton**) userData);
out = new automaton::EpsilonNFA(this->convert(regexp)); out = new automaton::Automaton(this->convert(regexp));
} }
   
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <regexp/RegExp.h> #include <regexp/RegExp.h>
#include <regexp/formal/FormalRegExpElements.h> #include <regexp/formal/FormalRegExpElements.h>
#include <regexp/unbounded/UnboundedRegExpElements.h> #include <regexp/unbounded/UnboundedRegExpElements.h>
#include <automaton/Automaton.h>
#include <automaton/FSM/EpsilonNFA.h> #include <automaton/FSM/EpsilonNFA.h>
   
namespace conversions namespace conversions
...@@ -35,7 +36,7 @@ public: ...@@ -35,7 +36,7 @@ public:
* @param regexp regexp to convert * @param regexp regexp to convert
* @return nondeterministic finite automaton with epsilon transitions accepting language described by the regexp * @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> template<class T>
static automaton::EpsilonNFA convert(const T& regexp); static automaton::EpsilonNFA convert(const T& regexp);
......
...@@ -13,6 +13,13 @@ ...@@ -13,6 +13,13 @@
   
namespace determinize { 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) { automaton::State NFADeterminizer::createDFAState(const std::set<automaton::State>& nfaStates) {
std::set<label::Label> labelSet; std::set<label::Label> labelSet;
...@@ -77,4 +84,59 @@ automaton::DFA NFADeterminizer::determinize(const automaton::NFA& nfa) { ...@@ -77,4 +84,59 @@ automaton::DFA NFADeterminizer::determinize(const automaton::NFA& nfa) {
return res; 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;
} }
...@@ -10,16 +10,19 @@ ...@@ -10,16 +10,19 @@
   
#include <set> #include <set>
   
#include "automaton/common/State.h" #include <automaton/common/State.h>
#include "automaton/FSM/NFA.h" #include <automaton/Automaton.h>
#include "automaton/FSM/DFA.h" #include <automaton/FSM/NFA.h>
#include <automaton/FSM/DFA.h>
#include <exception/AlibException.h>
   
namespace determinize { namespace determinize {
   
/** /**
* Class for running determinization algorithm on fsm. * Class for running determinization algorithm on fsm.
*/ */
class NFADeterminizer { class NFADeterminizer : public automaton::VisitableAutomatonBase::const_visitor_type {
   
private: private:
   
...@@ -41,14 +44,33 @@ private: ...@@ -41,14 +44,33 @@ private:
* @return set of states from nondeterministic fsm * @return set of states from nondeterministic fsm
*/ */
static std::set<automaton::State> recreateNFAStates(const automaton::State& dfaState); 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: public:
   
/** /**
* @param nfsm nondeterministic final-state machine given for determinization * @param nfsm nondeterministic final-state machine given for determinization
* @return DFA
* Runs determinization algorithm on nondeterministic fsm given in constructor. * 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 */ } /* namespace determinize */
......
...@@ -12,13 +12,23 @@ ...@@ -12,13 +12,23 @@
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
   
#include "alphabet/Symbol.h" #include <alphabet/Symbol.h>
#include "label/IntegerLabel.h" #include <label/IntegerLabel.h>
   
#include "automaton/Automaton.h" #include <exception/AlibException.h>
#include <automaton/Automaton.h>
   
namespace minimize { 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) { automaton::DFA MinimizeDFA::minimize(const automaton::DFA& dfa) {
if(dfa.getFinalStates().size() == 0) { if(dfa.getFinalStates().size() == 0) {
automaton::DFA result(automaton::State(0)); automaton::DFA result(automaton::State(0));
...@@ -131,4 +141,59 @@ automaton::DFA MinimizeDFA::minimize(const automaton::DFA& dfa) { ...@@ -131,4 +141,59 @@ automaton::DFA MinimizeDFA::minimize(const automaton::DFA& dfa) {
return result; 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 */ } /* namespace minimize */
...@@ -8,14 +8,36 @@ ...@@ -8,14 +8,36 @@
#ifndef MINIMIZE_DFA_H_ #ifndef MINIMIZE_DFA_H_
#define MINIMIZE_DFA_H_ #define MINIMIZE_DFA_H_
   
#include "automaton/FSM/DFA.h" #include <automaton/Automaton.h>
#include <automaton/FSM/DFA.h>
   
namespace minimize { namespace minimize {
   
class MinimizeDFA { class MinimizeDFA : public automaton::VisitableAutomatonBase::const_visitor_type {
public: public:
/**
* @param dfa automaton to minimize
*/
static automaton::Automaton minimize(const automaton::Automaton& dfa);
static automaton::DFA minimize(const automaton::DFA& 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;
}; };
   
} }
......
...@@ -31,22 +31,20 @@ void re2faTest::testThompson() { ...@@ -31,22 +31,20 @@ void re2faTest::testThompson() {
regexp::RegExpFromStringParser parser(inputs); regexp::RegExpFromStringParser parser(inputs);
regexp::RegExp regexp1( parser.parseValue() ); regexp::RegExp regexp1( parser.parseValue() );
   
conversions::re2fa::Thompson thompson1; automaton::Automaton enfa1 = conversions::re2fa::Thompson::convert(regexp1);
automaton::EpsilonNFA enfa1 = thompson1.convert(regexp1);
   
regexp::RegExp regexp2( conversions::fa2re::Algebraic::convert(enfa1) ); regexp::RegExp regexp2( conversions::fa2re::Algebraic::convert(enfa1) );
   
conversions::re2fa::Thompson thompson2; automaton::Automaton enfa2 = conversions::re2fa::Thompson::convert(regexp2);
automaton::EpsilonNFA enfa2 = thompson2.convert(regexp2);
   
automaton::NFA nfa1 = epsilon::FSMEpsilonRemover::remove(enfa1); automaton::Automaton nfa1 = epsilon::FSMEpsilonRemover::remove(enfa1);
automaton::NFA nfa2 = epsilon::FSMEpsilonRemover::remove(enfa2); automaton::Automaton nfa2 = epsilon::FSMEpsilonRemover::remove(enfa2);
   
automaton::DFA dfa1 = determinize::NFADeterminizer::determinize(nfa1); automaton::Automaton dfa1 = determinize::NFADeterminizer::determinize(nfa1);
automaton::DFA dfa2 = determinize::NFADeterminizer::determinize(nfa2); automaton::Automaton dfa2 = determinize::NFADeterminizer::determinize(nfa2);
   
automaton::DFA mdfa1 = minimize::MinimizeDFA::minimize(dfa1); automaton::Automaton mdfa1 = minimize::MinimizeDFA::minimize(dfa1);
automaton::DFA mdfa2 = minimize::MinimizeDFA::minimize(dfa2); automaton::Automaton mdfa2 = minimize::MinimizeDFA::minimize(dfa2);
   
CPPUNIT_ASSERT( mdfa1 == mdfa2); CPPUNIT_ASSERT( mdfa1 == mdfa2);
} }
......
...@@ -4,35 +4,26 @@ ...@@ -4,35 +4,26 @@
//============================================================================ //============================================================================
   
#include <iostream> #include <iostream>
#include <string>
#include <set>
   
#include "exception/AlibException.h" #include <exception/AlibException.h>
#include "factory/DataFactory.hpp" #include <factory/DataFactory.hpp>
#include "minimize/dfa/MinimizeDFA.h" #include "minimize/dfa/MinimizeDFA.h"
   
int main(int argc, char** argv) { int main(int argc, char** argv) {
   
try { try {
automaton::DFA* automatonPointer = NULL;
if (argc == 2 && std::string("-h").compare(argv[1]) == 0) { if (argc == 2 && std::string("-h").compare(argv[1]) == 0) {
std::cout << "Automaton minimize." << std::endl << "Usage: aminimize automaton.xml" << std::endl; std::cout << "Automaton minimize." << std::endl << "Usage: aminimize automaton.xml" << std::endl;
return -1; return -1;
} else if (argc == 1 || (argc == 2 && std::string("--").compare(argv[1]) == 0)) { } 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) { } 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 { } else {
std::cout << "Automaton minimize require deterministic finite automaton" << std::endl; std::cout << "Automaton minimize require deterministic finite automaton" << std::endl;
return 1; return 1;
} }
automaton::DFA res = minimize::MinimizeDFA::minimize(*automatonPointer);
alib::DataFactory::toStdout(res);
delete automatonPointer;
   
return 0; return 0;
   
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment