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

DFA normalization

parent b00fc496
No related branches found
No related tags found
No related merge requests found
/*
* Normalize.cpp
* NormalizeDFA.cpp
*
* Created on: Dec 9, 2013
* Author: honza
*/
* Author: JanTravnicek */
 
#include "Normalize.h"
#include "NormalizeDFA.h"
 
#include <map>
#include <deque>
......@@ -14,71 +13,62 @@
#include <algorithm>
#include <sstream>
#include <iostream>
#include "AlibException.h"
#include "exception/AlibException.h"
 
#include "alphabet/Symbol.h"
#include "automaton/FSM/TransitionFSM.h"
#include "label/Label.h"
#include "label/IntegerLabel.h"
 
automaton::State fromInteger(int number) {
std::stringstream ss;
ss << number;
return automaton::State(ss.str());
}
namespace normalize {
 
bool transitionSymbolComparator(const automaton::TransitionFSM& a, const automaton::TransitionFSM& b) {
return a.getInput() < b.getInput();
automaton::State fromInteger(int number) {
return automaton::State(label::Label(label::IntegerLabel(number)));
}
 
automaton::FSM Normalize::normalize(automaton::FSM& fsm) {
automaton::DFA NormalizeDFA::normalize(automaton::DFA& fsm) {
int counter = 0;
std::map<automaton::State, int > normalizationData;
std::deque<automaton::State > processingData;
normalizationData.insert(std::pair<automaton::State, int>(*(fsm.getInitialStates().begin()), counter++));
processingData.push_back(*(fsm.getInitialStates().begin()));
normalizationData.insert(std::pair<automaton::State, int>(fsm.getInitialState(), counter++));
processingData.push_back(fsm.getInitialState());
while(!processingData.empty()) {
automaton::State current = processingData.front();
processingData.pop_front();
const std::set<automaton::TransitionFSM> transitionsSet = fsm.getTransitionsFromState(current);
std::vector<automaton::TransitionFSM> transitions;
std::map<std::pair<automaton::State, alphabet::Symbol>, automaton::State> transitionsMap = fsm.getTransitionsFromState(current);
// Transitions are trivialy sorted by input symbol (from state is the same)
std::copy(transitionsSet.begin(), transitionsSet.end(), std::back_inserter(transitions));
std::sort (transitions.begin(), transitions.end(), transitionSymbolComparator);
for(auto iter = transitions.begin(); iter != transitions.end(); iter++) {
if(normalizationData.find(iter->getTo()) == normalizationData.end()) {
normalizationData.insert(std::pair<automaton::State, int>(iter->getTo(), counter++));
processingData.push_back(iter->getTo());
for(auto iter = fsm.getTransitions().begin(); iter != fsm.getTransitions().end(); iter++) {
if(normalizationData.find(iter->second) == normalizationData.end()) {
normalizationData.insert(std::pair<automaton::State, int>(iter->second, counter++));
processingData.push_back(iter->second);
}
}
}
if(normalizationData.size() != fsm.getStates().size()) {
throw alib::AlibException("Automaton normalize require minimal deterministic finite automaton");
throw exception::AlibException("Automaton normalize require minimal deterministic finite automaton");
}
automaton::FSM result;
for(auto iter = fsm.getInputAlphabet().begin(); iter != fsm.getInputAlphabet().end(); iter++) {
result.addInputSymbol(*iter);
}
automaton::DFA result(fromInteger(normalizationData.find(fsm.getInitialState())->second));
result.setInputSymbols(fsm.getInputAlphabet());
for(auto iter = fsm.getStates().begin(); iter != fsm.getStates().end(); iter++) {
result.addState(fromInteger(normalizationData.find(*iter)->second));
}
for(auto iter = fsm.getInitialStates().begin(); iter != fsm.getInitialStates().end(); iter++) {
result.addInitialState(fromInteger(normalizationData.find(*iter)->second));
}
for(auto iter = fsm.getFinalStates().begin(); iter != fsm.getFinalStates().end(); iter++) {
result.addFinalState(fromInteger(normalizationData.find(*iter)->second));
}
for(auto iter = fsm.getTransitions().begin(); iter != fsm.getTransitions().end(); iter++) {
result.addTransition(fromInteger(normalizationData.find(iter->getFrom())->second), iter->getInput(), fromInteger(normalizationData.find(iter->getTo())->second));
result.addTransition(fromInteger(normalizationData.find(iter->first.first)->second), iter->first.second, fromInteger(normalizationData.find(iter->second)->second));
}
 
return result;
}
}
/*
* NormalizeDFA.h
*
* Created on: Dec 9, 2013
* Author: Jan Travnicek
*/
#ifndef NORMALIZE_DFA_H_
#define NORMALIZE_DFA_H_
#include "automaton/FSM/DFA.h"
namespace normalize {
class NormalizeDFA {
public:
static automaton::DFA normalize(automaton::DFA& dfa);
};
}
#endif /* NORMALIZE_DFA_H_ */
#include <list>
#include "normalizeTest.h"
#include "label/StringLabel.h"
#include "label/IntegerLabel.h"
#include "label/Label.h"
#include "alphabet/LabeledSymbol.h"
#include "normalize/dfa/NormalizeDFA.h"
#define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y))
CPPUNIT_TEST_SUITE_REGISTRATION( normalizeTest );
void normalizeTest::setUp() {
}
void normalizeTest::tearDown() {
}
void normalizeTest::testNormalize() {
automaton::DFA automaton(automaton::State(label::Label(label::IntegerLabel(1))));
automaton.addState(automaton::State(label::Label(label::IntegerLabel(1))));
automaton.addState(automaton::State(label::Label(label::IntegerLabel(2))));
automaton.addState(automaton::State(label::Label(label::IntegerLabel(3))));
automaton.addInputSymbol(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("a")))));
automaton.addInputSymbol(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("b")))));
automaton.addTransition(automaton::State(label::Label(label::IntegerLabel(1))), alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("a")))), automaton::State(label::Label(label::IntegerLabel(2))));
automaton.addTransition(automaton::State(label::Label(label::IntegerLabel(2))), alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("b")))), automaton::State(label::Label(label::IntegerLabel(3))));
automaton.addFinalState(automaton::State(label::Label(label::IntegerLabel(3))));
automaton::DFA normalized = normalize::NormalizeDFA::normalize(automaton);
CPPUNIT_ASSERT(normalized.getStates().size() == 3);
}
#ifndef NORMALIZE_TEST_H_
#define NORMALIZE_TEST_H_
#include <cppunit/extensions/HelperMacros.h>
class normalizeTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE( normalizeTest );
CPPUNIT_TEST( testNormalize );
CPPUNIT_TEST_SUITE_END();
public:
void setUp();
void tearDown();
void testNormalize();
};
#endif // NORMALIZE_TEST_H_
CC=g++
EXECUTABLE=anormalize
CCFLAGS= -std=c++11 -O2 -c -Wall -I../alib/src
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
/*
* Normalize.h
*
* Created on: Dec 9, 2013
* Author: honza
*/
#ifndef NORMALIZE_H
#define NORMALIZE_H
#include "automaton/FSM/FSM.h"
class Normalize {
public:
static automaton::FSM normalize(automaton::FSM& fsm);
};
#endif /* NORMALIZE_H */
//============================================================================
// Name : aminimize.cpp
// Author : Jan Travnicek
//============================================================================
#include <iostream>
#include <string>
#include <set>
#include "AutomatonFactory.h"
#include "AlibException.h"
#include "automaton/AutomatonParser.h"
#include "Normalize.h"
using namespace std;
using namespace automaton;
using namespace alib;
int main(int argc, char** argv) {
UnknownAutomaton automaton;
try {
if (argc == 2 && string("-h").compare(argv[1]) == 0) {
cout << "Automaton normalize.\nUsage: anormalize automaton.xml\n";
return -1;
} else if (argc == 1 || (argc == 2 && string("--").compare(argv[1]) == 0)) {
automaton = AutomatonFactory::fromStdin();
if(!AutomatonFactory::isFSM(automaton)) {
cout << "Automaton normalize require minimal deterministic finite automaton\n";
return 1;
}
} else if (argc == 2) {
automaton = AutomatonFactory::fromFile(argv[1]);
if(!AutomatonFactory::isFSM(automaton)) {
cout << "Automaton normalize require minimal deterministic finite automaton\n";
return 1;
}
} else {
cout << "Automaton normalize require finite automaton\n";
return 1;
}
automaton::FSM fsm = AutomatonFactory::buildFSM(automaton);
if(!fsm.isDeterministic()) {
cout << "Automaton normalize require minimal deterministic finite automaton\n";
return 1;
}
automaton::FSM res = Normalize::normalize(fsm);
res.toXML(cout);
return 0;
} catch (AlibException& e) {
cout << e.getCause() << endl;
return 0;
}
}
SHELL:=/bin/bash
EXECUTABLE:=anormalize2
LDFLAGS= -L../alib2data/lib -L../alib2algo/lib -rdynamic -lxml2 -lalib2data -lalib2algo -Wl,-rpath,.
OBJECTS:=$(patsubst src/%.cpp, obj/%.o, $(shell find src/ -name *cpp))
.PHONY: all build clean
all: build
bin/$(EXECUTABLE): obj/ $(OBJECTS)
mkdir -p bin
$(CXX) $(OBJECTS) -o $@ $(LDFLAGS)
obj/makefile: makefile
mkdir -p $(dir $@)
echo "SHELL:=/bin/bash" >> $@
echo "SRCDIR:=" >> $@
echo "DEPTH:=" >> $@
echo "" >> $@
echo "CXXFLAGS:= -std=c++11 -Og -g -c -Wall -pedantic -Wextra -I../../\$$(DEPTH)alib2data/src/ -I../../\$$(DEPTH)alib2algo/src -I/usr/include/libxml2/" >> $@
echo "" >> $@
echo "SOURCES:= \$$(shell find ../\$$(DEPTH)src/\$$(SRCDIR) -maxdepth 1 -type f -name \"*.cpp\")" >> $@
echo "DEPENDENCIES:= \$$(patsubst ../\$$(DEPTH)src/\$$(SRCDIR)%.cpp, ../\$$(DEPTH)obj/\$$(SRCDIR)%.d, \$$(SOURCES))" >> $@
echo "OBJECTS:= \$$(patsubst %.d, %.o, \$$(DEPENDENCIES))" >> $@
echo "SOURCES_DIRS:= \$$(shell find ../\$$(DEPTH)src/\$$(SRCDIR) -maxdepth 1 -mindepth 1 -type d)" >> $@
echo "OBJECTS_DIRS:= \$$(patsubst ../\$$(DEPTH)src/\$$(SRCDIR)%, %/, \$$(SOURCES_DIRS))" >> $@
echo "OBJECTS_DIRS_MAKEFILES:= \$$(patsubst %, %makefile, \$$(OBJECTS_DIRS))" >> $@
echo "" >> $@
echo ".PHONY: all" >> $@
echo ".PRECIOUS: \$$(DEPENDECIES) \$$(OBJECTS_DIRS_MAKEFILES)" >> $@
echo "" >> $@
echo "all: \$$(OBJECTS_DIRS) \$$(OBJECTS)" >> $@
echo "" >> $@
echo "%.d:" >> $@
echo " @echo \"\$$(shell sha1sum <<< \"\$$@\" | sed \"s/ -//g\") = \\$$\$$(shell (\\$$\$$(CXX) -MM \\$$\$$(CXXFLAGS) \$$(patsubst ../\$$(DEPTH)obj/\$$(SRCDIR)%.d,../\$$(DEPTH)src/\$$(SRCDIR)%.cpp, \$$@) 2>/dev/null || echo \\\"\$$(patsubst ../\$$(DEPTH)obj/\$$(SRCDIR)%.d,../\$$(DEPTH)src/\$$(SRCDIR)%.cpp, \$$@) FORCE\\\") | sed \\\"s/.*://g;s/\\\\\\\\\\\\\\\\//g\\\")\" >> \$$@" >> $@
echo " @echo \"\$$(patsubst %.d,%.o, \$$@): \\$$\$$(\$$(shell sha1sum <<< \"\$$@\" | sed \"s/ -//g\"))\" >> \$$@" >> $@
echo " @echo \" \\$$\$$(CXX) \\$$\$$(CXXFLAGS) \\$$\$$< -o \$$(patsubst %.d,%.o, \$$@)\" >> \$$@" >> $@
echo "" >> $@
echo "%/makefile:" >> $@
echo " mkdir -p \$$(dir \$$@)" >> $@
echo " cp makefile \$$@" >> $@
echo "" >> $@
echo "%/: FORCE | %/makefile" >> $@
echo " @accesstime=\`stat -c %Y \$$@\` && \\" >> $@
echo " \$$(MAKE) -C \$$@ SRCDIR=\$$(SRCDIR)\$$(notdir \$$(patsubst %/, %, \$$@))/ DEPTH=\$$(DEPTH)../ && \\" >> $@
echo " accesstime2=\`stat -c %Y \$$@\` && \\" >> $@
echo " if [ "\$$\$$accesstime" -ne "\$$\$$accesstime2" ]; then \\" >> $@
echo " touch .; \\" >> $@
echo " fi" >> $@
echo "" >> $@
echo "FORCE:" >> $@
echo "" >> $@
echo "-include \$$(DEPENDENCIES)" >> $@
obj/: FORCE | obj/makefile
$(MAKE) -C $@
$(OBJECTS): obj/
build: bin/$(EXECUTABLE)
clean:
$(RM) -r *.o *.d bin lib obj test-bin test-obj
FORCE:
//============================================================================
// Name : anormalize.cpp
// Author : Jan Travnicek
//============================================================================
#include <iostream>
#include <string>
#include <set>
#include "exception/AlibException.h"
#include "factory/DataFactory.hpp"
#include "normalize/dfa/NormalizeDFA.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 normalize." << std::endl << "Usage: anormalize 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());
} else if (argc == 2) {
automatonPointer = static_cast<automaton::DFA*>(std::move(alib::DataFactory::fromFile<automaton::DFA>(argv[1])).plunder());
} else {
std::cout << "Automaton normalize require deterministic finite automaton" << std::endl;
return 1;
}
automaton::DFA res = normalize::NormalizeDFA::normalize(*automatonPointer);
alib::DataFactory::toStdout(res);
delete automatonPointer;
return 0;
} catch (const exception::AlibException& exception) {
alib::DataFactory::toStdout(exception);
return 1;
} catch(...) {
return 127;
}
}
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