diff --git a/acompaction2/makefile b/acompaction2/makefile new file mode 100644 index 0000000000000000000000000000000000000000..905d096b31fd2139233d69a9e7e7141a3d21e927 --- /dev/null +++ b/acompaction2/makefile @@ -0,0 +1,128 @@ +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 + diff --git a/acompaction2/src/acompaction.cpp b/acompaction2/src/acompaction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bf1e8fb96f344250d2ec336f8f681649f6179e56 --- /dev/null +++ b/acompaction2/src/acompaction.cpp @@ -0,0 +1,48 @@ +/* + * 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; + } +} diff --git a/alib2algo/src/automaton/transform/Compaction.cpp b/alib2algo/src/automaton/transform/Compaction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aee716ea161f81b9f810f08946fca11aff7e1633 --- /dev/null +++ b/alib2algo/src/automaton/transform/Compaction.cpp @@ -0,0 +1,141 @@ +/* + * 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 */ diff --git a/alib2algo/src/automaton/transform/Compaction.h b/alib2algo/src/automaton/transform/Compaction.h new file mode 100644 index 0000000000000000000000000000000000000000..520ad9a028d9dfb1f26b97bcfdb061a97e8a0066 --- /dev/null +++ b/alib2algo/src/automaton/transform/Compaction.h @@ -0,0 +1,48 @@ +/* + * 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_ */ diff --git a/makefile b/makefile index fc64ef68283bac6da8acd3a05b102fb8bf5079dc..89afbc69f21c028a9becac570a24260d21cec8d6 100644 --- a/makefile +++ b/makefile @@ -7,6 +7,7 @@ SUBDIRS_LIBS = alib2algo SUBDIRS_BINS = aecho2 \ aconversions2 \ aconvert2 \ + acompaction2 \ aderivation2 \ adeterminize2 \ acompare2 \