Skip to content
Snippets Groups Projects
Commit a713f488 authored by Jan Trávníček's avatar Jan Trávníček
Browse files

implement Automaton run

parent b273d647
No related branches found
No related tags found
No related merge requests found
CC=g++
EXECUTABLE=aaccept
CCFLAGS= -std=c++11 -O2 -g -c -Wall -I../alib/src -I/usr/include/libxml2/
LDFLAGS= -L../alib/lib -lxml2 -lalib -Wl,-rpath,.
SOURCES=$(shell find src/ -name *cpp)
OBJECTS=$(patsubst src/%.cpp, obj/%.o, $(SOURCES))
all: $(SOURCES) bin/$(EXECUTABLE)
bin/$(EXECUTABLE): $(OBJECTS)
mkdir -p bin
$(CC) $(OBJECTS) -o $@ $(LDFLAGS)
obj/%.o: src/%.cpp
mkdir -p $(dir $@)
$(CC) $(CCFLAGS) $< -o $@
clean:
$(RM) -r *.o *.d bin obj
/*
* NFARun.cpp
*
* Created on: 14. 2. 2014
* Author: tomas
*/
#include "NFARun.h"
#include <iostream>
using namespace alib;
using namespace automaton;
using namespace std;
NFARun::NFARun( const FSM & fsm ) : m_fsm( fsm )
{
}
bool NFARun::simulate( const list<Symbol> & string ) const
{
if( ! checkAlphabet( string ) )
throw AlibException( "String alphabet does not match automaton alphabet." );
for( const auto & state : m_fsm.getInitialStates( ) )
if( configuration( state, string ) )
return true;
return false;
}
bool NFARun::checkAlphabet( const list<Symbol> & string ) const
{
const auto & alphabet = m_fsm.getInputAlphabet( );
for( const auto & symbol : string )
if( alphabet.find( symbol ) == alphabet.end( ) )
return false;
return true;
}
bool NFARun::configuration( const State & state, const list<Symbol> & string ) const
{
if( string.empty( ) )
return m_fsm.getFinalStates( ).find( state ) != m_fsm.getFinalStates( ).end( );
const Symbol & inputSymbol = string.front( );
list<Symbol> newString = string;
newString.pop_front( );
for( const auto & transition : m_fsm.getTransitionsFromState( state ) )
if( transition.getInput( ) == inputSymbol && configuration( transition.getTo( ), newString ) )
return true;
return false;
}
State NFARun::createUniqueState( const string & desiredName ) const
{
//TODO: No need for this method after utils from aconversions project is merged into alib
State s( desiredName );
if( m_fsm.getStates( ).find( s ) == m_fsm.getStates( ).end( ) )
return s;
int i = 0;
while( true )
{
State s( desiredName + to_string( i ++ ) );
// state not present in totalFSM
if( m_fsm.getStates( ).find( s ) == m_fsm.getStates( ).end( ) )
return s;
}
throw AlibException( "WordAcceptance - Unable to create trash state" );
}
/*
* NFARun.h
*
* Created on: 14. 2. 2014
* Author: tomas
*/
#ifndef NFARUN_H_
#define NFARUN_H_
#include <automaton/FSM/FSM.h>
#include <alphabet/Symbol.h>
#include <AlibException.h>
#include <climits>
#include <list>
#include <map>
#include <stdexcept>
/**
* @brief Simulates NFA run
*/
class NFARun
{
public:
NFARun( const automaton::FSM & fsm );
/**
* Simulates run of FSM with input word
* @param word Input word
* @return bool boolean value whether word was accepted
*/
bool simulate( const std::list<alphabet::Symbol> & string ) const;
private:
/**
* Create unique state in automaton. If state with desired name is
* already present, tries to create state with same name and integer suffix
* @param desiredName desired name of state
* @return new unique state
* @throws AutomatonException if was unable to create unique state (counter
* reached INT_MAX)
*/
automaton::State createUniqueState( const std::string & desiredName ) const;
/**
* @return true if all symbols are in the automata's input alphabet
*/
bool checkAlphabet( const std::list<alphabet::Symbol> & string ) const;
/*
* Puts automaton into configuration Q x T* and checks if
* @param state state of automata
* @param string unreaded substring
* @return true if in configuration ( q, \eps ), q is accepting state
*/
bool configuration( const automaton::State & state, const std::list<alphabet::Symbol> & string ) const;
automaton::FSM m_fsm;
};
#endif /* NFARUN_H_ */
#include <iostream>
#include <string>
#include <list>
#include <AlibException.h>
#include <automaton/AutomatonParser.h>
#include <automaton/UnknownAutomaton.h>
#include <AutomatonFactory.h>
#include <sax/SaxInterface.h>
#include "NFARun.h"
using namespace alib;
using namespace automaton;
using namespace alphabet;
using namespace std;
using namespace sax;
/*
* Usage:
* aacept.fsm "a" "b" "cc" < fsm.xml (accepts FSM.xml word <a><b><cc> ?)
*/
int main(int argc, char** argv)
{
try
{
list<Token> tokens;
string input(istreambuf_iterator<char>(cin), (istreambuf_iterator<char>()));
SaxInterface::parseMemory(input, tokens);
UnknownAutomaton unknownAutomaton = AutomatonParser::parse(tokens);
FSM fsm = AutomatonFactory::buildFSM( unknownAutomaton );
NFARun nfa( fsm );
list<Symbol> word;
for( int i = 1; i < argc ; i++ )
word.push_back( Symbol ( argv[ i ] ) );
if( nfa.simulate( word ) )
{
cout << "Automaton accepted word." << endl;
return 0;
}
else
{
cout << "Automaton did not accept word" << endl;
return 1;
}
}
catch( AlibException & e )
{
cout << e.what() << endl;
return 255;
}
return 0;
}
SHELL:=/bin/bash
EXECUTABLE:=aaccept2
define NEW_LINE
endef
export NEW_LINE
LDFLAGS_DEBUG:=-L../alib2data/lib-debug -L../alib2algo/lib-debug -rdynamic -lxml2 -lalib2data -lalib2algo -Wl,-rpath,.
LDFLAGS_RELEASE:=-L../alib2data/lib-release -L../alib2algo/lib-release -rdynamic -lxml2 -lalib2data -lalib2algo -Wl,-rpath,.
OBJECTS_DEBUG:=$(patsubst src/%.cpp, obj-debug/%.o, $(shell find src/ -name *cpp))
OBJECTS_RELEASE:=$(patsubst src/%.cpp, obj-release/%.o, $(shell find src/ -name *cpp))
.PHONY: all build-debug clean-debug doc
all:
@echo "What to do master?"
obj%/makefile: makefile
mkdir -p $(dir $@)
echo "\
SHELL:=/bin/bash$${NEW_LINE}\
SRCDIR:=$${NEW_LINE}\
DEPTH:=$${NEW_LINE}\
OBJECTS_BASE_DIR:=$${NEW_LINE}\
$${NEW_LINE}\
define NEW_LINE$${NEW_LINE}\
$${NEW_LINE}\
$${NEW_LINE}\
endef$${NEW_LINE}\
$${NEW_LINE}\
export NEW_LINE$${NEW_LINE}\
$${NEW_LINE}\
CXXFLAGS:= -std=c++11 \$$(CXX_OTHER_FLAGS) -c -Wall -pedantic -Wextra -fPIC -I/usr/include/libxml2/ -I../../\$$(DEPTH)alib2data/src/ -I../../\$$(DEPTH)alib2algo/src/$${NEW_LINE}\
$${NEW_LINE}\
SOURCES:= \$$(shell find ../\$$(DEPTH)\$$(SOURCES_BASE_DIR)/\$$(SRCDIR) -maxdepth 1 -type f -name \"*.cpp\")$${NEW_LINE}\
DEPENDENCIES:= \$$(patsubst ../\$$(DEPTH)\$$(SOURCES_BASE_DIR)/\$$(SRCDIR)%.cpp, ../\$$(DEPTH)\$$(OBJECTS_BASE_DIR)/\$$(SRCDIR)%.d, \$$(SOURCES))$${NEW_LINE}\
OBJECTS:= \$$(patsubst %.d, %.o, \$$(DEPENDENCIES))$${NEW_LINE}\
SOURCES_DIRS:= \$$(shell find ../\$$(DEPTH)\$$(SOURCES_BASE_DIR)/\$$(SRCDIR) -maxdepth 1 -mindepth 1 -type d)$${NEW_LINE}\
OBJECTS_DIRS:= \$$(patsubst ../\$$(DEPTH)\$$(SOURCES_BASE_DIR)/\$$(SRCDIR)%, %/, \$$(SOURCES_DIRS))$${NEW_LINE}\
OBJECTS_DIRS_MAKEFILES:= \$$(patsubst %, %makefile, \$$(OBJECTS_DIRS))$${NEW_LINE}\
$${NEW_LINE}\
.PHONY: all$${NEW_LINE}\
.PRECIOUS: \$$(DEPENDECIES) \$$(OBJECTS_DIRS_MAKEFILES)$${NEW_LINE}\
$${NEW_LINE}\
all: \$$(OBJECTS_DIRS) \$$(OBJECTS)$${NEW_LINE}\
$${NEW_LINE}\
%.d: makefile$${NEW_LINE}\
@echo \"\\$${NEW_LINE}\
\$$(shell sha1sum <<< \"\$$@\" | sed \"s/ -//g\") = \\$$\$$(shell (\\$$\$$(CXX) -MM \\$$\$$(CXXFLAGS) \$$(patsubst ../\$$(DEPTH)\$$(OBJECTS_BASE_DIR)/\$$(SRCDIR)%.d,../\$$(DEPTH)\$$(SOURCES_BASE_DIR)/\$$(SRCDIR)%.cpp, \$$@) 2>/dev/null || echo \\\"\$$(patsubst ../\$$(DEPTH)\$$(OBJECTS_BASE_DIR)/\$$(SRCDIR)%.d,../\$$(DEPTH)\$$(SOURCES_BASE_DIR)/\$$(SRCDIR)%.cpp, \$$@) FORCE\\\") | sed \\\"s/.*://g;s/\\\\\\\\\\\\\\\\//g\\\")\$$\$${NEW_LINE}\\$${NEW_LINE}\
\$$(patsubst %.d,%.o, \$$@): \\$$\$$(\$$(shell sha1sum <<< \"\$$@\" | sed \"s/ -//g\")) makefile\$$\$${NEW_LINE}\\$${NEW_LINE}\
\\$$\$$(CXX) \\$$\$$(CXXFLAGS) \\$$\$$< -o \$$(patsubst %.d,%.o, \$$@)\$$\$${NEW_LINE}\\$${NEW_LINE}\
\" > \$$@$${NEW_LINE}\
$${NEW_LINE}\
%/makefile: makefile$${NEW_LINE}\
mkdir -p \$$(dir \$$@)$${NEW_LINE}\
cp makefile \$$@$${NEW_LINE}\
$${NEW_LINE}\
%/: FORCE | %/makefile$${NEW_LINE}\
@accesstime=\`stat -c %Y \$$@\` && \\$${NEW_LINE}\
\$$(MAKE) -C \$$@ SRCDIR=\$$(SRCDIR)\$$(notdir \$$(patsubst %/, %, \$$@))/ DEPTH=\$$(DEPTH)../ OBJECTS_BASE_DIR=\$$(OBJECTS_BASE_DIR) SOURCES_BASE_DIR=\$$(SOURCES_BASE_DIR) CXX_OTHER_FLAGS=\"\$$(CXX_OTHER_FLAGS)\" && \\$${NEW_LINE}\
accesstime2=\`stat -c %Y \$$@\` && \\$${NEW_LINE}\
if [ "\$$\$$accesstime" -ne "\$$\$$accesstime2" ]; then \\$${NEW_LINE}\
touch .; \\$${NEW_LINE}\
fi$${NEW_LINE}\
$${NEW_LINE}\
FORCE:$${NEW_LINE}\
$${NEW_LINE}\
-include \$$(DEPENDENCIES)" > $@
debug: build-debug
release: build-release
clean: clean-debug clean-release
$(RM) -r doc
bin-debug/$(EXECUTABLE): obj-debug/ $(OBJECTS_DEBUG)
mkdir -p $(dir $@)
$(CXX) $(OBJECTS_DEBUG) -o $@ $(LDFLAGS_DEBUG)
bin-release/$(EXECUTABLE): obj-release/ $(OBJECTS_RELEASE)
mkdir -p $(dir $@)
$(CXX) $(OBJECTS_RELEASE) -o $@ $(LDFLAGS_RELEASE)
obj-debug/: FORCE | obj-debug/makefile
$(MAKE) -C $@ OBJECTS_BASE_DIR=obj-debug SOURCES_BASE_DIR=src CXX_OTHER_FLAGS="-g -O0"
obj-release/: FORCE | obj-release/makefile
$(MAKE) -C $@ OBJECTS_BASE_DIR=obj-release SOURCES_BASE_DIR=src CXX_OTHER_FLAGS="-O3"
$(OBJECTS_DEBUG): obj-debug/
$(OBJECTS_RELEASE): obj-release/
build-debug: bin-debug/$(EXECUTABLE)
build-release: bin-release/$(EXECUTABLE)
clean-debug:
$(RM) -r *.o *.d bin-debug obj-debug
clean-release:
$(RM) -r *.o *.d bin-release obj-release
FORCE:
doc:
doxygen
//============================================================================
// Name : aminimize.cpp
// Author : Jan Travnicek
//============================================================================
#include <iostream>
#include <exception/AlibException.h>
#include <factory/DataFactory.hpp>
#include "automaton/accept/Accept.h"
int main(int argc, char** argv) {
try {
if (argc == 2 && std::string("-h").compare(argv[1]) == 0) {
std::cout << "Automaton run." << std::endl << "Usage: aaccept string.xml < automaton.xml" << std::endl;
return -1;
} else if (argc == 2) {
automaton::Automaton automaton = alib::DataFactory::fromStdin<automaton::Automaton>();
string::LinearString string = alib::DataFactory::fromFile<string::LinearString>(argv[1]);
if(automaton::accept::Accept::accept(automaton, string)) {
std::cout << "Accept" << std::endl;
return 0;
} else {
std::cout << "Reject" << std::endl;
return 1;
}
} else {
std::cout << "Automaton accept require automaton on stdin and string as argument" << std::endl;
return 2;
}
return 0;
} catch (const exception::AlibException& exception) {
alib::DataFactory::toStdout(exception);
return 2;
} catch(...) {
return 127;
}
}
/*
* AcceptLeftRG.h
*
* Created on: 9. 2. 2014
* Author: Jan Travnicek
*/
#include "Accept.h"
#include <exception/AlibException.h>
#include <automaton/FSM/DFA.h>
#include <automaton/FSM/NFA.h>
#include <automaton/PDA/DPDA.h>
#include <deque>
namespace automaton {
namespace accept {
bool Accept::accept(const automaton::Automaton& automaton, const string::LinearString& string) {
std::pair<const string::LinearString*, bool> data(&string, false);
automaton.getData().Accept((void*) &data, Accept::ACCEPT);
return data.second;
}
bool Accept::accept(const automaton::DFA& automaton, const string::LinearString& string) {
automaton::State state = automaton.getInitialState();
for(const alphabet::Symbol& symbol : string.getContent()) {
auto transitions = automaton.getTransitionsFromState(state);
auto next = transitions.find(std::make_pair(state, symbol));
if(next == transitions.end()) return false;
state = next->second;
}
return automaton.getFinalStates().count(state);
}
bool recursiveAccept(const automaton::NFA& automaton, const automaton::State& state, const string::LinearString& string) {
if( string.getContent().empty( ) )
return automaton.getFinalStates().count( state );
const alphabet::Symbol & inputSymbol = string.getContent().front( );
string::LinearString newString(std::vector<alphabet::Symbol>{ string.getContent().begin() + 1, string.getContent().end()});
for( const auto & transition : automaton.getTransitionsFromState( state ) )
for(const auto& to : transition.second)
if( transition.first.second == inputSymbol && recursiveAccept( automaton, to, newString ) )
return true;
return false;
}
bool Accept::accept( const automaton::NFA& automaton, const string::LinearString & string ) {
return recursiveAccept(automaton, automaton.getInitialState(), string);
}
bool Accept::accept(const automaton::DPDA& automaton, const string::LinearString& string) {
automaton::State state = automaton.getInitialState();
std::deque<alphabet::Symbol> pushdownStore;
for(const alphabet::Symbol& symbol : string.getContent()) {
auto transitions = automaton.getTransitionsFromState(state);
auto transition = transitions.begin();
int pushdownStoreSize = pushdownStore.size();
for(auto transition = transitions.begin(); transition != transitions.end(); transition++) {
if(std::get<1>(transition->first) != symbol) continue;
const std::vector<alphabet::Symbol> & pop = std::get<2>(transition->first);
int popSize = pop.size();
if(pushdownStoreSize < popSize) continue;
bool sign = true;
for(int i = 1; i <= popSize; i++) {
if(pop[popSize - i] != pushdownStore[pushdownStoreSize - i]) {
sign = false;
break;
}
}
if(!sign) continue;
break;
}
if(transition == transitions.end()) return false;
for(auto pop : std::get<2>(transition->first)) pushdownStore.pop_back();
state = transition->second.first;
for(const alphabet::Symbol& push : transition->second.second) pushdownStore.push_back(push);
}
if(automaton.getFinalStates().empty()) {
return pushdownStore.empty();
} else {
return automaton.getFinalStates().count(state);
}
}
void Accept::Visit(void*, const automaton::EpsilonNFA& ) const {
throw exception::AlibException("Unsupported automaton type EpsilonNFA");
}
void Accept::Visit(void*, const automaton::MultiInitialStateNFA& ) const {
throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA");
}
void Accept::Visit(void* data, const automaton::NFA& automaton) const {
std::pair<const string::LinearString*, bool> & res = *((std::pair<const string::LinearString*, bool>*) data);
res.second = this->accept(automaton, *res.first);
}
void Accept::Visit(void* data, const automaton::DFA& automaton) const {
std::pair<const string::LinearString*, bool> & res = *((std::pair<const string::LinearString*, bool>*) data);
res.second = this->accept(automaton, *res.first);
}
void Accept::Visit(void*, const automaton::ExtendedNFA& ) const {
throw exception::AlibException("Unsupported automaton type ExtendedNFA");
}
void Accept::Visit(void*, const automaton::CompactNFA& ) const {
throw exception::AlibException("Unsupported automaton type CompactNFA");
}
void Accept::Visit(void* data, const DPDA& automaton) const {
std::pair<const string::LinearString*, bool> & res = *((std::pair<const string::LinearString*, bool>*) data);
res.second = this->accept(automaton, *res.first);
}
void Accept::Visit(void*, const SinglePopDPDA&) const {
throw exception::AlibException("Unsupported automaton type SinglePopDPDA");
}
void Accept::Visit(void*, const InputDrivenNPDA&) const {
throw exception::AlibException("Unsupported automaton type InputDrivenNPDA");
}
void Accept::Visit(void*, const VisiblyPushdownDPDA&) const {
throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA");
}
void Accept::Visit(void*, const VisiblyPushdownNPDA&) const {
throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA");
}
void Accept::Visit(void*, const RealTimeHeightDeterministicDPDA&) const {
throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA");
}
void Accept::Visit(void*, const RealTimeHeightDeterministicNPDA&) const {
throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA");
}
void Accept::Visit(void*, const NPDA&) const {
throw exception::AlibException("Unsupported automaton type NPDA");
}
void Accept::Visit(void*, const SinglePopNPDA&) const {
throw exception::AlibException("Unsupported automaton type SinglePopNPDA");
}
void Accept::Visit(void*, const OneTapeDTM&) const {
throw exception::AlibException("Unsupported automaton type OneTapeDTM");
}
const Accept Accept::ACCEPT;
} /* namespace accept */
} /* namespace automaton */
/*
* Accept.h
*
* Created on: 9. 2. 2014
* Author: Jan Travnicek
*/
#ifndef _AUTOMATON_ACCEPT_H__
#define _AUTOMATON_ACCEPT_H__
#include <automaton/Automaton.h>
#include <string/LinearString.h>
namespace automaton {
namespace accept {
class Accept : public automaton::VisitableAutomatonBase::const_visitor_type {
public:
/**
* Performs conversion.
* @return left regular grammar equivalent to source automaton.
*/
static bool accept(const automaton::Automaton& automaton, const string::LinearString& string);
static bool accept(const automaton::DFA& automaton, const string::LinearString& string);
static bool accept(const automaton::NFA& automaton, const string::LinearString& string);
static bool accept(const automaton::DPDA& automaton, const string::LinearString& string);
private:
void Visit(void*, const EpsilonNFA& automaton) const;
void Visit(void*, const MultiInitialStateNFA& automaton) const;
void Visit(void*, const NFA& automaton) const;
void Visit(void*, const DFA& automaton) const;
void Visit(void*, const ExtendedNFA& automaton) const;
void Visit(void*, const CompactNFA& automaton) const;
void Visit(void*, const DPDA& automaton) const;
void Visit(void*, const SinglePopDPDA& automaton) const;
void Visit(void*, const InputDrivenNPDA& automaton) const;
void Visit(void*, const VisiblyPushdownDPDA& automaton) const;
void Visit(void*, const VisiblyPushdownNPDA& automaton) const;
void Visit(void*, const RealTimeHeightDeterministicDPDA& automaton) const;
void Visit(void*, const RealTimeHeightDeterministicNPDA& automaton) const;
void Visit(void*, const NPDA& automaton) const;
void Visit(void*, const SinglePopNPDA& automaton) const;
void Visit(void*, const OneTapeDTM& automaton) const;
static const Accept ACCEPT;
};
} /* namespace accept */
} /* namespace automaton */
#endif /* _AUTOMATON_ACCEPT_H__ */
...@@ -4,7 +4,8 @@ BINFOLDER = bin ...@@ -4,7 +4,8 @@ BINFOLDER = bin
   
CORE_LIB = alib2data CORE_LIB = alib2data
SUBDIRS_LIBS = alib2algo SUBDIRS_LIBS = alib2algo
SUBDIRS_BINS = acat2 \ SUBDIRS_BINS = aaccept2 \
acat2 \
aconversions2 \ aconversions2 \
aconvert2 \ aconvert2 \
aderivation2 \ aderivation2 \
......
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