Skip to content
Snippets Groups Projects
Commit ff35da6e authored by Tomáš Pecka's avatar Tomáš Pecka Committed by Jan Trávníček
Browse files

algo: DFA compaction

parent 0c3a03ec
No related branches found
No related tags found
No related merge requests found
SHELL:=/bin/bash
EXECUTABLE:=acompaction2
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
/*
* acompaction.cpp
*
* Created on: 2. 11. 2014
* Author: Tomas Pecka
*/
#include <iostream>
#include <tclap/CmdLine.h>
#include "exception/AlibException.h"
#include "factory/XmlDataFactory.hpp"
#include "automaton/transform/Compaction.h"
int main(int argc, char** argv) {
try {
TCLAP::CmdLine cmd("Automaton compaction binary", ' ', "0.01");
TCLAP::ValueArg<std::string> input( "i", "input", "Automaton to compactify", false, "-", "file");
cmd.add( input );
cmd.parse(argc, argv);
std::list<sax::Token> tokens;
if(input.isSet()) {
if(input.getValue() == "-") {
sax::SaxParseInterface::parseStdin(tokens);
} else {
sax::SaxParseInterface::parseFile(input.getValue(), tokens);
}
} else {
sax::SaxParseInterface::parseStdin(tokens);
}
alib::XmlDataFactory::toStdout(automaton::transform::Compaction::convert(alib::XmlDataFactory::fromTokens<automaton::Automaton>(tokens)));
return 0;
} catch (const exception::AlibException& exception) {
alib::XmlDataFactory::toStdout(exception);
return 1;
} catch(const TCLAP::ArgException& exception) {
std::cout << exception.error() << std::endl;
return 2;
} catch(...) {
return 127;
}
}
/*
* Compaction.cpp
*
* Created on: 2. 11. 2014
* Author: Tomas Pecka
*/
#include "Compaction.h"
#include <exception/AlibException.h>
#include <automaton/common/State.h>
#include <automaton/FSM/CompactNFA.h>
#include <automaton/FSM/DFA.h>
#include <stack>
#include <tuple>
namespace automaton {
namespace transform {
automaton::Automaton Compaction::convert(const automaton::Automaton& automaton) {
automaton::Automaton* out = NULL;
automaton.getData().Accept((void*) &out, Compaction::COMPACTION);
automaton::Automaton res(std::move(*out));
delete out;
return res;
}
automaton::CompactNFA Compaction::convert(const automaton::CompactNFA& automaton)
{
return automaton;
}
automaton::CompactNFA Compaction::convert(const automaton::DFA& automaton)
{
automaton::CompactNFA res(automaton.getInitialState());
res.setInputAlphabet(automaton.getInputAlphabet());
string::LinearString path;
path.setAlphabet(automaton.getInputAlphabet());
std::map<automaton::State, bool> visited;
for(const auto& state : automaton.getStates())
visited.insert(std::make_pair(state, automaton.getInitialState() == state));
std::stack<std::tuple<automaton::State, automaton::State, alphabet::Symbol>> stack; // state x lastFork x symbol we used to go to that state
for(const auto& transition: automaton.getTransitionsFromState(automaton.getInitialState()))
{
stack.push(std::make_tuple(transition.second, automaton.getInitialState(), transition.first.second));
}
if(automaton.getFinalStates().count(automaton.getInitialState()) > 0)
res.addFinalState(automaton.getInitialState());
while(!stack.empty())
{
const automaton::State q = std::get<0>(stack.top());
const automaton::State lastFork = std::get<1>(stack.top());
const alphabet::Symbol symbol = std::get<2>(stack.top());
stack.pop();
path.appendSymbol(symbol);
// only 1 child and nonfinal
if(automaton.getTransitionsFromState(q).size() == 1 && automaton.getFinalStates().count(q) == 0 && automaton.getInitialState() != q)
{
const auto& transition = * automaton.getTransitionsFromState(q).begin();
stack.push(std::make_tuple(transition.second, lastFork, transition.first.second));
}
else // fork or final state
{
res.addState(q);
if(automaton.getFinalStates().count(q))
res.addFinalState(q);
res.addTransition(lastFork, path, q);
path.setContent({});
for(const auto& transition : automaton.getTransitionsFromState(q))
{
if(visited.find(transition.second)->second == false)
{
stack.push(std::make_tuple(transition.second, q, transition.first.second));
visited.find(transition.second)->second = true;
}
}
}
}
return res;
}
automaton::CompactNFA Compaction::convert(const automaton::NFA& automaton)
{
automaton::CompactNFA res(automaton.getInitialState());
// TODO
return res;
}
void Compaction::Visit(void* data, const CompactNFA& automaton) const
{
automaton::Automaton*& out = *((automaton::Automaton**) data);
out = new automaton::Automaton(this->convert(automaton));
}
void Compaction::Visit(void* data, const DFA& automaton) const
{
automaton::Automaton*& out = *((automaton::Automaton**) data);
out = new automaton::Automaton(this->convert(automaton));
}
void Compaction::Visit(void*, const EpsilonNFA&) const
{
throw exception::AlibException("Unsupported automaton type EpsilonNFA");
}
void Compaction::Visit(void*, const ExtendedNFA&) const
{
throw exception::AlibException("Unsupported automaton type ExtendedNFA");
}
void Compaction::Visit(void*, const MultiInitialStateNFA&) const
{
throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA");
}
void Compaction::Visit(void* data, const NFA& automaton) const
{
automaton::Automaton*& out = *((automaton::Automaton**) data);
out = new automaton::Automaton(this->convert(automaton));
}
const Compaction Compaction::COMPACTION;
} /* namespace transform */
} /* namespace automaton */
/*
* Compaction.h
*
* Created on: 2. 11. 2014
* Author: Tomas Pecka
*/
#ifndef COMPACTION_H_
#define COMPACTION_H_
#include "automaton/Automaton.h"
namespace automaton {
namespace transform {
/**
* Transforms FSM to CompactNFA
*/
class Compaction : public VisitableConstFSMBase {
public:
static automaton::CompactNFA convert( const automaton::DFA& automaton);
static automaton::CompactNFA convert( const automaton::NFA& automaton);
static automaton::CompactNFA convert( const automaton::CompactNFA& automaton);
/**
* Transforms
* @param automaton FSM to transform
* @return CompactNFA equivalent to given automaton
*/
static automaton::Automaton convert( const automaton::Automaton & automaton );
private:
void Visit(void*, const CompactNFA& automaton) const;
void Visit(void*, const DFA& automaton) const;
void Visit(void*, const EpsilonNFA& automaton) const;
void Visit(void*, const ExtendedNFA& automaton) const;
void Visit(void*, const MultiInitialStateNFA& automaton) const;
void Visit(void*, const NFA& automaton) const;
static const Compaction COMPACTION;
};
} /* namespace transform */
} /* namespace automaton */
#endif /* COMPACTION_H_ */
......@@ -7,6 +7,7 @@ SUBDIRS_LIBS = alib2algo
SUBDIRS_BINS = aecho2 \
aconversions2 \
aconvert2 \
acompaction2 \
aderivation2 \
adeterminize2 \
acompare2 \
......
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