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

algo: StateElimination

parent 434d49d2
No related branches found
No related tags found
No related merge requests found
......@@ -7,7 +7,8 @@
 
#include "ConversionHandler.h"
 
//#include "conversions/fa2re/StateElimination.h"
#include "conversions/fa2re/unbounded/StateEliminationUnbounded.h"
#include "conversions/fa2re/formal/StateEliminationFormal.h"
#include "conversions/fa2re/BrzozowskiAlgebraic.h"
 
#include "conversions/re2fa/Glushkov.h"
......@@ -54,7 +55,7 @@ void ConversionHandler::convert( void )
{
if( m_source == FINITE_AUTOMATON )
convertFSM( );
else if( m_source == REGULAR_EXPRESSION )
else if( isRegExp(m_source) )
convertRE( );
else if( isGrammar( m_source ) )
convertRG( );
......@@ -68,7 +69,7 @@ void ConversionHandler::convertFSM( void )
{
if( m_target == FINITE_AUTOMATON )
throw exception::AlibException( "ConversionHandler: No valid conversion from FSM to FSM." );
else if( m_target == REGULAR_EXPRESSION )
else if( isRegExp( m_target ) )
convertFSMtoRE( );
else if( isGrammar( m_target ) )
convertFSMtoRG( );
......@@ -80,7 +81,7 @@ void ConversionHandler::convertRE( void )
{
if( m_target == FINITE_AUTOMATON )
convertREtoFSM( );
else if( m_target == REGULAR_EXPRESSION )
else if( isRegExp( m_target ) )
throw exception::AlibException( "ConversionHandler: No valid conversion from RE to RE." );
else if( isGrammar( m_target ) )
convertREtoRG( );
......@@ -92,7 +93,7 @@ void ConversionHandler::convertRG( void )
{
if( m_target == FINITE_AUTOMATON )
convertRGtoFSM( );
else if( m_target == REGULAR_EXPRESSION )
else if( isRegExp( m_target ) )
convertRGtoRE( );
else if( isGrammar( m_target ) )
convertRGtoRG( );
......@@ -102,8 +103,40 @@ void ConversionHandler::convertRG( void )
 
// ----------------------------------------------------------------------------
 
void ConversionHandler::convertFSMtoRE( void )
void ConversionHandler::convertFSMtoRE(void)
{
switch( m_target )
{
case REGULAR_EXPRESSION_FORMAL:
convertFSMtoREF();
break;
default:
convertFSMtoREU();
break;
}
}
void ConversionHandler::convertFSMtoREF(void)
{
const automaton::Automaton automaton = alib::DataFactory::fromTokens<automaton::Automaton>(m_tokens);
switch( m_algorithm )
{
case BRZOZOWSKI_ALGEBRAIC:
break;
case STATE_ELIMINATION:
default: {
alib::DataFactory::toStdout(fa2re::StateEliminationFormal::convert(automaton));
break;
}
}
}
void ConversionHandler::convertFSMtoREU( void )
{
const automaton::Automaton automaton = alib::DataFactory::fromTokens<automaton::Automaton>(m_tokens);
switch( m_algorithm )
{
case BRZOZOWSKI_ALGEBRAIC: {
......@@ -123,9 +156,7 @@ void ConversionHandler::convertFSMtoRE( void )
}
case STATE_ELIMINATION:
default: {
/*fa2re::StateElimination conv( fsm );
regexp::UnboundedRegExp re = conv.convert();
alib::DataFactory::toStdout(re);*/
alib::DataFactory::toStdout(fa2re::StateEliminationUnbounded::convert(automaton));
break;
}
}
......@@ -368,7 +399,9 @@ ConversionHandler::TFormalism ConversionHandler::parseFormalismFromString( const
return FINITE_AUTOMATON;
 
if( target == "re" || target == "regexp" || target == "regex" )
return REGULAR_EXPRESSION;
return REGULAR_EXPRESSION_UNBOUNDED;
if (target == "formalre" || target == "formalregexp" || target == "formalregex")
return REGULAR_EXPRESSION_FORMAL;
 
if( target == "rrg" || target == "rg" || target == "grammar" )
return RIGHT_REGULAR_GRAMMAR;
......@@ -387,7 +420,10 @@ ConversionHandler::TFormalism ConversionHandler::parseFormalismFromTokens( void
return FINITE_AUTOMATON;
 
if( xmlMark == "regexp" || xmlMark == "unboundedRegexp" )
return REGULAR_EXPRESSION;
return REGULAR_EXPRESSION_UNBOUNDED;
if(xmlMark == "formalRegExp")
return REGULAR_EXPRESSION_FORMAL;
 
if( xmlMark == "RightRG" )
return RIGHT_REGULAR_GRAMMAR;
......
......@@ -69,13 +69,16 @@ public:
LEFT_LINEAR_GRAMMAR,
RIGHT_LINEAR_GRAMMAR,
 
REGULAR_EXPRESSION,
REGULAR_EXPRESSION_UNBOUNDED,
REGULAR_EXPRESSION_FORMAL,
 
UNKNOWN,
};
#define isGrammar(x) ( (x) == REGULAR_GRAMMAR || (x) == LEFT_REGULAR_GRAMMAR || (x) == RIGHT_REGULAR_GRAMMAR \
|| (x) == LINEAR_GRAMMAR || (x) == LEFT_LINEAR_GRAMMAR || (x) == RIGHT_LINEAR_GRAMMAR )
 
#define isRegExp(x) ( (x) == REGULAR_EXPRESSION_FORMAL || (x) == REGULAR_EXPRESSION_UNBOUNDED )
ConversionHandler( std::list<sax::Token> & tokens, const std::string & target, const std::string & algorithm, std::ostream & out );
void convert( void );
 
......@@ -86,6 +89,8 @@ private:
 
void convertFSM( void );
void convertFSMtoRE( void );
void convertFSMtoREF( void );
void convertFSMtoREU( void );
void convertFSMtoRG( void );
void convertFSMtoLRG( void );
void convertFSMtoRRG( void );
......
/*
* StateEliminationFormal.cpp
*
* Created on: 9. 2. 2014
* Author: Tomas Pecka
*/
#include "StateEliminationFormal.h"
#include <regexp/formal/FormalRegExp.h>
#include <label/StringLabel.h>
#include <exception/AlibException.h>
#include "../../../regexp/RegExpOptimize.h"
namespace fa2re
{
template<class T>
regexp::RegExp StateEliminationFormal::convert(const T& automaton)
{
if(automaton.getFinalStates().size() == 0)
return regexp::RegExp{regexp::FormalRegExp(regexp::FormalRegExpEmpty())};
// steps 1 + 2
automaton::ExtendedNFA extendedAutomaton = constructExtendedNFA(automaton);
extendExtendedNFA(extendedAutomaton);
// step 3 - Exterminate!
// select all states that are neither final nor initial
std::set<automaton::State> statesToEliminate = extendedAutomaton.getStates();
statesToEliminate.erase(*extendedAutomaton.getInitialStates().begin());
statesToEliminate.erase(*extendedAutomaton.getFinalStates().begin());
for(const auto& state : statesToEliminate)
extendedAutomaton = eliminateState(extendedAutomaton, state);
// step 4
//regexp::RegExpOptimize opt;
regexp::FormalRegExpConcatenation concat(
std::move(*transition(extendedAutomaton, *extendedAutomaton.getInitialStates().begin(), *extendedAutomaton.getFinalStates().begin())),
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);
regexp::RegExp res = std::move(*out);
delete out;
return res;
}
void StateEliminationFormal::Visit(void*, const automaton::UnknownAutomaton&) const
{
throw exception::AlibException("Unsupported automaton type UnknownAutomaton");
}
void StateEliminationFormal::Visit(void* data, const automaton::EpsilonNFA& automaton) const
{
regexp::RegExp* & out = *((regexp::RegExp**) data);
out = new regexp::RegExp(convert(automaton));
}
void StateEliminationFormal::Visit(void* data, const automaton::NFA& automaton) const
{
regexp::RegExp* & out = *((regexp::RegExp**) data);
out = new regexp::RegExp(convert(automaton));
}
void StateEliminationFormal::Visit(void* data, const automaton::DFA& automaton) const
{
regexp::RegExp* & out = *((regexp::RegExp**) data);
out = new regexp::RegExp(convert(automaton));
}
void StateEliminationFormal::Visit(void* data, const automaton::ExtendedNFA& automaton) const
{
regexp::RegExp* & out = *((regexp::RegExp**) data);
out = new regexp::RegExp(convert(automaton));
}
void StateEliminationFormal::Visit(void*, const automaton::CompactNFA& ) const
{
throw exception::AlibException("Unsupported automaton type CompactNFA");
}
void StateEliminationFormal::Visit(void*, const automaton::NPDA&) const
{
throw exception::AlibException("Unsupported automaton type NPDA");
}
void StateEliminationFormal::Visit(void*, const automaton::SinglePopNPDA&) const
{
throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
}
void StateEliminationFormal::Visit(void*, const automaton::OneTapeDTM&) const
{
throw exception::AlibException("Unsupported automaton type OneTapeDTM");
}
automaton::ExtendedNFA StateEliminationFormal::eliminateState(const automaton::ExtendedNFA& extendedAutomaton, const automaton::State& q)
{
automaton::ExtendedNFA newAutomaton;
newAutomaton.setStates(extendedAutomaton.getStates());
newAutomaton.removeState(q); // preserve all states but q (the one to eliminate)
newAutomaton.setInputSymbols(extendedAutomaton.getInputAlphabet());
newAutomaton.setInitialStates(extendedAutomaton.getInitialStates()); // sure that q is neither initial nor final (follows from step 2 - extending ExtendedNFA)
newAutomaton.setFinalStates(extendedAutomaton.getFinalStates());
// regexp::RegExpOptimize opt;
for(const auto& p: newAutomaton.getStates())
{
for(const auto& r : newAutomaton.getStates())
{
regexp::FormalRegExpConcatenation concat(
std::move(*transition(extendedAutomaton, p, q)),
regexp::FormalRegExpConcatenation(
regexp::FormalRegExpIteration(std::move(*transition(extendedAutomaton, q, q))),
std::move(*transition(extendedAutomaton, q, r))
)
);
regexp::FormalRegExpAlternation alt(
std::move(*transition(extendedAutomaton, p, r)),
concat
);
// regexp::FormalRegExp transitionRegExp(opt.optimize(regexp::FormalRegExp(alt)));
regexp::FormalRegExp transitionRegExp(alt);
transitionRegExp.setAlphabet(extendedAutomaton.getInputAlphabet());
newAutomaton.addTransition(p, regexp::RegExp{transitionRegExp}, r);
}
}
return newAutomaton;
}
const regexp::FormalRegExpElement* StateEliminationFormal::transition(const automaton::ExtendedNFA& automaton, const automaton::State& from, const automaton::State& to)
{
std::vector<regexp::FormalRegExpElement*> alt;
for(const auto& transition: automaton.getTransitionsFromState(from))
if(transition.second.count(to) > 0)
alt.push_back(static_cast<const regexp::FormalRegExp&>(transition.first.second.getData()).getRegExp().clone());
size_t size = alt.size();
if(size == 0) return new regexp::FormalRegExpEmpty();
if(size == 1) return alt.at(0);
regexp::FormalRegExpAlternation* ret = new regexp::FormalRegExpAlternation(std::move(*alt.at(--size)), std::move(*alt.at(--size)));
while(size)
{
regexp::FormalRegExpElement* left = alt.at(--size);
regexp::FormalRegExpElement* right = ret;
ret = new regexp::FormalRegExpAlternation(std::move(*left), std::move(*right));
delete left;
delete right;
}
return ret;
}
template<>
automaton::ExtendedNFA StateEliminationFormal::constructExtendedNFA(const automaton::NFA& automaton)
{
automaton::ExtendedNFA extendedAutomaton;
extendedAutomaton.setStates(automaton.getStates());
extendedAutomaton.setInputSymbols(automaton.getInputAlphabet());
extendedAutomaton.setInitialStates(automaton.getInitialStates());
extendedAutomaton.setFinalStates(automaton.getFinalStates());
for(const auto& transition : automaton.getTransitions()) // pair<State, symb/eps> -> set<State>
{
regexp::FormalRegExp regexp(regexp::FormalRegExpSymbol(transition.first.second));
regexp.setAlphabet(extendedAutomaton.getInputAlphabet());
for(const auto& to : transition.second)
extendedAutomaton.addTransition(transition.first.first, regexp::RegExp{regexp}, to);
}
return extendedAutomaton;
}
template<>
automaton::ExtendedNFA StateEliminationFormal::constructExtendedNFA(const automaton::DFA& automaton)
{
automaton::ExtendedNFA extendedAutomaton;
extendedAutomaton.setStates(automaton.getStates());
extendedAutomaton.setInputSymbols(automaton.getInputAlphabet());
extendedAutomaton.setInitialStates(std::set<automaton::State>{automaton.getInitialState()});
extendedAutomaton.setFinalStates(automaton.getFinalStates());
for(const auto& transition : automaton.getTransitions()) // pair<State, symb/eps> -> set<State>
{
regexp::FormalRegExp regexp(regexp::FormalRegExpSymbol(transition.first.second));
regexp.setAlphabet(extendedAutomaton.getInputAlphabet());
extendedAutomaton.addTransition(transition.first.first, regexp::RegExp{regexp}, transition.second);
}
return extendedAutomaton;
}
template<>
automaton::ExtendedNFA StateEliminationFormal::constructExtendedNFA(const automaton::EpsilonNFA& automaton)
{
automaton::ExtendedNFA extendedAutomaton;
extendedAutomaton.setStates(automaton.getStates());
extendedAutomaton.setInputSymbols(automaton.getInputAlphabet());
extendedAutomaton.setInitialStates(automaton.getInitialStates());
extendedAutomaton.setFinalStates(automaton.getFinalStates());
for(const auto& transition : automaton.getSymbolTransitions()) // pair<State, symb/eps> -> set<State>
{
regexp::FormalRegExp regexp(regexp::FormalRegExpSymbol(transition.first.second));
regexp.setAlphabet(extendedAutomaton.getInputAlphabet());
for(const auto& to : transition.second)
extendedAutomaton.addTransition(transition.first.first, regexp::RegExp{regexp}, to);
}
for(const auto& transition : automaton.getEpsilonTransitions())
{
regexp::FormalRegExp regexp;
regexp.setRegExp(regexp::FormalRegExpEpsilon());
regexp.setAlphabet(extendedAutomaton.getInputAlphabet());
for(const auto& to : transition.second)
extendedAutomaton.addTransition(transition.first, regexp::RegExp{regexp}, to);
}
return extendedAutomaton;
}
template<>
automaton::ExtendedNFA StateEliminationFormal::constructExtendedNFA(const automaton::ExtendedNFA& automaton)
{
return automaton;
}
void StateEliminationFormal::extendExtendedNFA(automaton::ExtendedNFA& automaton)
{
const automaton::State& initState = *automaton.getInitialStates().begin();
if(automaton.getFinalStates().count(initState) > 0 || automaton.getTransitionsToState(initState).size() > 0 )
{
const automaton::State q0 = automaton::createUniqueState(initState, automaton.getStates());
automaton.addState(q0);
regexp::FormalRegExp regexp;
regexp.setRegExp(regexp::FormalRegExpEpsilon());
regexp.setAlphabet(automaton.getInputAlphabet());
automaton.addTransition(q0, regexp::RegExp{regexp}, initState);
const std::set<automaton::State> automatonInitialStates = automaton.getInitialStates();
for(const auto& state: automatonInitialStates)
automaton.removeInitialState(state);
automaton.addInitialState(q0);
}
if(automaton.getFinalStates().size() > 1)
{
const automaton::State f = automaton::createUniqueState(automaton::State(label::Label(label::StringLabel("f"))), automaton.getStates());
automaton.addState(f);
const std::set<automaton::State> automatonFinalStates = automaton.getFinalStates();
for(const auto &state : automatonFinalStates)
{
regexp::FormalRegExp regexp;
regexp.setRegExp(regexp::FormalRegExpEpsilon());
regexp.setAlphabet(automaton.getInputAlphabet());
automaton.addTransition(state, regexp::RegExp{regexp}, f);
automaton.removeFinalState(state);
}
automaton.addFinalState(f);
}
}
const StateEliminationFormal StateEliminationFormal::STATE_ELIMINATION;
} /* namespace fa2re */
/*
* StateEliminationFormal.h
*
* Created on: 9. 2. 2014
* Author: Tomas Pecka
*/
#ifndef STATEELIMINATIONFORMAL_H_
#define STATEELIMINATIONFORMAL_H_
#include <regexp/RegExp.h>
#include <regexp/formal/FormalRegExpElements.h>
#include <automaton/Automaton.h>
#include <automaton/FSM/DFA.h>
#include <automaton/FSM/NFA.h>
#include <automaton/FSM/EpsilonNFA.h>
#include <automaton/FSM/ExtendedNFA.h>
namespace fa2re
{
/**
* Converts FSM to RE using State Elimination algorithm.
* Source: Melichar 2.118
*/
class StateEliminationFormal : public automaton::VisitableAutomatonBase::const_visitor_type
{
public:
/**
* Performs conversion.
* @return regular expression equivalent to source NFA.
*/
template<class T>
static regexp::RegExp convert(const T& 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;
template<class T>
static automaton::ExtendedNFA constructExtendedNFA(const T& automaton);
static void extendExtendedNFA(automaton::ExtendedNFA& automaton);
static const regexp::FormalRegExpElement* transition(const automaton::ExtendedNFA& automaton, const automaton::State& from, const automaton::State& to);
static automaton::ExtendedNFA eliminateState(const automaton::ExtendedNFA& extendedAutomaton, const automaton::State& state);
static const StateEliminationFormal STATE_ELIMINATION;
};
} /* namespace fa2re */
#endif /* STATEELIMINATIONFORMAL_H_ */
/*
* StateEliminationUnbounded.cpp
*
* Created on: 9. 2. 2014
* Author: Tomas Pecka
*/
#include "StateEliminationUnbounded.h"
#include <regexp/unbounded/UnboundedRegExp.h>
#include <label/StringLabel.h>
#include <exception/AlibException.h>
#include <factory/DataFactory.hpp>
#include "../../../regexp/RegExpOptimize.h"
namespace fa2re
{
template<class T>
regexp::RegExp StateEliminationUnbounded::convert(const T& automaton)
{
if(automaton.getFinalStates().size() == 0)
return regexp::RegExp{regexp::UnboundedRegExp(regexp::UnboundedRegExpEmpty())};
// steps 1 + 2
automaton::ExtendedNFA extendedAutomaton = constructExtendedNFA(automaton);
extendExtendedNFA(extendedAutomaton);
// step 3 - Exterminate!
// select all states that are neither final nor initial
std::set<automaton::State> statesToEliminate = extendedAutomaton.getStates();
statesToEliminate.erase(*extendedAutomaton.getInitialStates().begin());
statesToEliminate.erase(*extendedAutomaton.getFinalStates().begin());
for(const auto& state : statesToEliminate)
extendedAutomaton = eliminateState(extendedAutomaton, state);
// step 4
regexp::RegExpOptimize opt;
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);
regexp::RegExp res = std::move(*out);
delete out;
return res;
}
void StateEliminationUnbounded::Visit(void*, const automaton::UnknownAutomaton&) const
{
throw exception::AlibException("Unsupported automaton type UnknownAutomaton");
}
void StateEliminationUnbounded::Visit(void* data, const automaton::EpsilonNFA& automaton) const
{
regexp::RegExp* & out = *((regexp::RegExp**) data);
out = new regexp::RegExp(convert(automaton));
}
void StateEliminationUnbounded::Visit(void* data, const automaton::NFA& automaton) const
{
regexp::RegExp* & out = *((regexp::RegExp**) data);
out = new regexp::RegExp(convert(automaton));
}
void StateEliminationUnbounded::Visit(void* data, const automaton::DFA& automaton) const
{
regexp::RegExp* & out = *((regexp::RegExp**) data);
out = new regexp::RegExp(convert(automaton));
}
void StateEliminationUnbounded::Visit(void* data, const automaton::ExtendedNFA& automaton) const
{
regexp::RegExp* & out = *((regexp::RegExp**) data);
out = new regexp::RegExp(convert(automaton));
}
void StateEliminationUnbounded::Visit(void*, const automaton::CompactNFA& ) const
{
throw exception::AlibException("Unsupported automaton type CompactNFA");
}
void StateEliminationUnbounded::Visit(void*, const automaton::NPDA&) const
{
throw exception::AlibException("Unsupported automaton type NPDA");
}
void StateEliminationUnbounded::Visit(void*, const automaton::SinglePopNPDA&) const
{
throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
}
void StateEliminationUnbounded::Visit(void*, const automaton::OneTapeDTM&) const
{
throw exception::AlibException("Unsupported automaton type OneTapeDTM");
}
automaton::ExtendedNFA StateEliminationUnbounded::eliminateState(const automaton::ExtendedNFA& extendedAutomaton, const automaton::State& q)
{
automaton::ExtendedNFA newAutomaton;
newAutomaton.setStates(extendedAutomaton.getStates());
newAutomaton.removeState(q); // preserve all states but q (the one to eliminate)
newAutomaton.setInputSymbols(extendedAutomaton.getInputAlphabet());
newAutomaton.setInitialStates(extendedAutomaton.getInitialStates()); // sure that q is neither initial nor final (follows from step 2 - extending ExtendedNFA)
newAutomaton.setFinalStates(extendedAutomaton.getFinalStates());
regexp::RegExpOptimize opt;
for(const auto& p: newAutomaton.getStates())
{
for(const auto& r : newAutomaton.getStates())
{
regexp::UnboundedRegExpConcatenation concat;
concat.appendElement(std::move(*transition(extendedAutomaton, p, q)));
concat.appendElement(regexp::UnboundedRegExpIteration(std::move(*transition(extendedAutomaton, q, q))));
concat.appendElement(std::move(*transition(extendedAutomaton, q, r)));
regexp::UnboundedRegExpAlternation alt;
alt.appendElement(std::move(*transition(extendedAutomaton, p, r)));
alt.appendElement(concat);
regexp::UnboundedRegExp transitionRegExp(opt.optimize(regexp::UnboundedRegExp(alt)));
transitionRegExp.setAlphabet(extendedAutomaton.getInputAlphabet());
newAutomaton.addTransition(p, regexp::RegExp{transitionRegExp}, r);
}
}
return newAutomaton;
}
const regexp::UnboundedRegExpElement* StateEliminationUnbounded::transition(const automaton::ExtendedNFA& automaton, const automaton::State& from, const automaton::State& to)
{
regexp::RegExpOptimize opt;
regexp::UnboundedRegExpAlternation ret;
for(const auto& transition: automaton.getTransitionsFromState(from))
if(transition.second.count(to) > 0)
ret.appendElement(static_cast<const regexp::UnboundedRegExp&>(transition.first.second.getData()).getRegExp());
return opt.optimize(regexp::UnboundedRegExp(ret)).getRegExp().clone();
}
template<>
automaton::ExtendedNFA StateEliminationUnbounded::constructExtendedNFA(const automaton::NFA& automaton)
{
automaton::ExtendedNFA extendedAutomaton;
extendedAutomaton.setStates(automaton.getStates());
extendedAutomaton.setInputSymbols(automaton.getInputAlphabet());
extendedAutomaton.setInitialStates(automaton.getInitialStates());
extendedAutomaton.setFinalStates(automaton.getFinalStates());
for(const auto& transition : automaton.getTransitions()) // pair<State, symb/eps> -> set<State>
{
regexp::UnboundedRegExp regexp(regexp::UnboundedRegExpSymbol(transition.first.second));
regexp.setAlphabet(extendedAutomaton.getInputAlphabet());
for(const auto& to : transition.second)
extendedAutomaton.addTransition(transition.first.first, regexp::RegExp{regexp}, to);
}
return extendedAutomaton;
}
template<>
automaton::ExtendedNFA StateEliminationUnbounded::constructExtendedNFA(const automaton::DFA& automaton)
{
automaton::ExtendedNFA extendedAutomaton;
extendedAutomaton.setStates(automaton.getStates());
extendedAutomaton.setInputSymbols(automaton.getInputAlphabet());
extendedAutomaton.setInitialStates(std::set<automaton::State>{automaton.getInitialState()});
extendedAutomaton.setFinalStates(automaton.getFinalStates());
for(const auto& transition : automaton.getTransitions()) // pair<State, symb/eps> -> set<State>
{
regexp::UnboundedRegExp regexp(regexp::UnboundedRegExpSymbol(transition.first.second));
regexp.setAlphabet(extendedAutomaton.getInputAlphabet());
extendedAutomaton.addTransition(transition.first.first, regexp::RegExp{regexp}, transition.second);
}
return extendedAutomaton;
}
template<>
automaton::ExtendedNFA StateEliminationUnbounded::constructExtendedNFA(const automaton::EpsilonNFA& automaton)
{
automaton::ExtendedNFA extendedAutomaton;
extendedAutomaton.setStates(automaton.getStates());
extendedAutomaton.setInputSymbols(automaton.getInputAlphabet());
extendedAutomaton.setInitialStates(automaton.getInitialStates());
extendedAutomaton.setFinalStates(automaton.getFinalStates());
for(const auto& transition : automaton.getSymbolTransitions()) // pair<State, symb/eps> -> set<State>
{
regexp::UnboundedRegExp regexp(regexp::UnboundedRegExpSymbol(transition.first.second));
regexp.setAlphabet(extendedAutomaton.getInputAlphabet());
for(const auto& to : transition.second)
extendedAutomaton.addTransition(transition.first.first, regexp::RegExp{regexp}, to);
}
for(const auto& transition : automaton.getEpsilonTransitions())
{
regexp::UnboundedRegExp regexp;
regexp.setRegExp(regexp::UnboundedRegExpEpsilon());
regexp.setAlphabet(extendedAutomaton.getInputAlphabet());
for(const auto& to : transition.second)
extendedAutomaton.addTransition(transition.first, regexp::RegExp{regexp}, to);
}
return extendedAutomaton;
}
template<>
automaton::ExtendedNFA StateEliminationUnbounded::constructExtendedNFA(const automaton::ExtendedNFA& automaton)
{
return automaton;
}
void StateEliminationUnbounded::extendExtendedNFA(automaton::ExtendedNFA& automaton)
{
const automaton::State& initState = *automaton.getInitialStates().begin();
if(automaton.getFinalStates().count(initState) > 0 || automaton.getTransitionsToState(initState).size() > 0 )
{
const automaton::State q0 = automaton::createUniqueState(initState, automaton.getStates());
automaton.addState(q0);
regexp::UnboundedRegExp regexp;
regexp.setRegExp(regexp::UnboundedRegExpEpsilon());
regexp.setAlphabet(automaton.getInputAlphabet());
automaton.addTransition(q0, regexp::RegExp{regexp}, initState);
const std::set<automaton::State> automatonInitialStates = automaton.getInitialStates();
for(const auto& state: automatonInitialStates)
automaton.removeInitialState(state);
automaton.addInitialState(q0);
}
if(automaton.getFinalStates().size() > 1)
{
const automaton::State f = automaton::createUniqueState(automaton::State(label::Label(label::StringLabel("f"))), automaton.getStates());
automaton.addState(f);
const std::set<automaton::State> automatonFinalStates = automaton.getFinalStates();
for(const auto &state : automatonFinalStates)
{
regexp::UnboundedRegExp regexp;
regexp.setRegExp(regexp::UnboundedRegExpEpsilon());
regexp.setAlphabet(automaton.getInputAlphabet());
automaton.addTransition(state, regexp::RegExp{regexp}, f);
automaton.removeFinalState(state);
}
automaton.addFinalState(f);
}
}
const StateEliminationUnbounded StateEliminationUnbounded::STATE_ELIMINATION;
} /* namespace fa2re */
/*
* StateEliminationUnbounded.h
*
* Created on: 9. 2. 2014
* Author: Tomas Pecka
*/
#ifndef STATEELIMINATIONUNBOUNDED_H_
#define STATEELIMINATIONUNBOUNDED_H_
#include <regexp/RegExp.h>
#include <regexp/unbounded/UnboundedRegExpElements.h>
#include <automaton/Automaton.h>
#include <automaton/FSM/DFA.h>
#include <automaton/FSM/NFA.h>
#include <automaton/FSM/EpsilonNFA.h>
#include <automaton/FSM/ExtendedNFA.h>
namespace fa2re
{
/**
* Converts FSM to RE using State Elimination algorithm.
* Source: Melichar 2.118
*/
class StateEliminationUnbounded : public automaton::VisitableAutomatonBase::const_visitor_type
{
public:
/**
* Performs conversion.
* @return regular expression equivalent to source NFA.
*/
template<class T>
static regexp::RegExp convert(const T& 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;
template<class T>
static automaton::ExtendedNFA constructExtendedNFA(const T& automaton);
static void extendExtendedNFA(automaton::ExtendedNFA& automaton);
static const regexp::UnboundedRegExpElement* transition(const automaton::ExtendedNFA& automaton, const automaton::State& from, const automaton::State& to);
static automaton::ExtendedNFA eliminateState(const automaton::ExtendedNFA& extendedAutomaton, const automaton::State& state);
static const StateEliminationUnbounded STATE_ELIMINATION;
};
} /* namespace fa2re */
#endif /* STATEELIMINATIONUNBOUNDED_H_ */
......@@ -85,7 +85,7 @@ function runTest2 {
fi
}
 
# $1 - aconversion sequence
# $1 - aconversion2 sequence
function runTest {
RES_GOOD=0
RES_FAIL=0
......@@ -167,22 +167,22 @@ runTest "./aconversions2 -t LRG | ./aconversions2 -t RRG | ./aconversions2 -t FA
runTest "./aconversions2 -t RE -a algebraic | ./aconversions2 -t FA -a brzozowski"
runTest "./aconversions2 -t RE -a algebraic | ./aconversions2 -t FA -a thompson"
runTest "./aconversions2 -t RE -a algebraic | ./aconversions2 -t FA -a glushkov "
#runTest "./aconversion -t RE -a elimination | ./aconversion -t FA -a brzozowski"
#runTest "./aconversion -t RE -a elimination | ./aconversion -t FA -a thompson"
#runTest "./aconversion -t RE -a elimination | ./aconversion -t FA -a glushkov"
runTest "./aconversions2 -t RE -a elimination | ./aconversions2 -t FA -a brzozowski"
runTest "./aconversions2 -t RE -a elimination | ./aconversions2 -t FA -a thompson"
runTest "./aconversions2 -t RE -a elimination | ./aconversions2 -t FA -a glushkov"
 
# FA -> RE -> RRG -> LRG -> FA
# covers: FA -> RE (Brz. algebraic, elimination), RE -> RRG ( Brz. derivation, Glushkov), RRG -> LRG, LRG -> FA
# runTest "./aconversion -t RE -a algebraic | ./aconversion -t RRG -a brzozowski | ./aconversion -t LRG | ./aconversion -t FA"
# runTest "./aconversion -t RE -a algebraic | ./aconversion -t RRG -a glushkov | ./aconversion -t LRG | ./aconversion -t FA"
# runTest "./aconversion -t RE -a elimination | ./aconversion -t RRG -a brzozowski | ./aconversion -t LRG | ./aconversion -t FA"
# runTest "./aconversion -t RE -a elimination | ./aconversion -t RRG -a glushkov | ./aconversion -t LRG | ./aconversion -t FA"
runTest "./aconversions2 -t RE -a algebraic | ./aconversions2 -t RRG -a brzozowski | ./aconversion2 -t LRG | ./aconversion2 -t FA"
runTest "./aconversions2 -ts2-t RE -a algebraic | ./aconversions2 -t RRG -a glushkov | ./aconversion2 -t LRG | ./aconversion2 -t FA"
runTest "./aconversions2 -ts2-t RE -a elimination | ./aconversions2 -t RRG -a brzozowski | ./aconversion2 -t LRG | ./aconversion2 -t FA"
runTest "./aconversions2 -ts2-t RE -a elimination | ./aconversions2 -t RRG -a glushkov | ./aconversion2 -t LRG | ./aconversion2 -t FA"
 
# FA -> RRG -> RE -> FA
# covers: FA -> RRG, FA -> LRG, RRG -> RE, LRG -> RE, RE -> FA (Brz. derivation, Thompson, Glushkov)
# runTest "./aconversion -t RRG | ./aconversion -t RE | ./aconversion -t FA -a brzozowski"
# runTest "./aconversion -t LRG | ./aconversion -t RE | ./aconversion -t FA -a brzozowski"
# runTest "./aconversion -t RRG | ./aconversion -t RE | ./aconversion -t FA -a thompson"
# runTest "./aconversion -t LRG | ./aconversion -t RE | ./aconversion -t FA -a thompson"
# runTest "./aconversion -t RRG | ./aconversion -t RE | ./aconversion -t FA -a glushkov"
# runTest "./aconversion -t LRG | ./aconversion -t RE | ./aconversion -t FA -a glushkov"
# runTest "./aconversion2 -t RRG | ./aconversion2 -t RE | ./aconversion2 -t FA -a brzozowski"
# runTest "./aconversion2 -t LRG | ./aconversion2 -t RE | ./aconversion2 -t FA -a brzozowski"
# runTest "./aconversion2 -t RRG | ./aconversion2 -t RE | ./aconversion2 -t FA -a thompson"
# runTest "./aconversion2 -t LRG | ./aconversion2 -t RE | ./aconversion2 -t FA -a thompson"
# runTest "./aconversion2 -t RRG | ./aconversion2 -t RE | ./aconversion2 -t FA -a glushkov"
# runTest "./aconversion2 -t LRG | ./aconversion2 -t RE | ./aconversion2 -t FA -a glushkov"
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