diff --git a/alangop2/makefile b/alangop2/makefile new file mode 100644 index 0000000000000000000000000000000000000000..1e4036e680cc48c7e75cfb3686bd37c9f80a9628 --- /dev/null +++ b/alangop2/makefile @@ -0,0 +1,128 @@ +SHELL:=/bin/bash +EXECUTABLE:=alangop2 + +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/alangop2/src/alangop.cpp b/alangop2/src/alangop.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7c3566564836974a9c886de5a46038865a334335 --- /dev/null +++ b/alangop2/src/alangop.cpp @@ -0,0 +1,114 @@ +/* + * alangop.cpp + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#include <tclap/CmdLine.h> +#include <vector> + +#include <factory/DataFactory.hpp> +#include <exception/AlibException.h> +#include <automaton/Automaton.h> + +#include <automaton/transform/AutomataConcatenationEpsilonTransition.h> +#include <automaton/transform/AutomataConcatenation.h> +#include <automaton/transform/AutomataIntersectionCartesianProduct.h> +#include <automaton/transform/AutomataUnionCartesianProduct.h> +#include <automaton/transform/AutomataUnionEpsilonTransition.h> +#include <automaton/transform/AutomatonIterationEpsilonTransition.h> +#include <automaton/transform/AutomatonIteration.h> + + +int main(int argc, char* argv[]) { + try { + TCLAP::CmdLine cmd("Stringology algorithm access binary", ' ', "0.01"); + + std::vector<std::string> allowed; + allowed.push_back("unionEpsilon"); + allowed.push_back("unionCartesian"); + allowed.push_back("concatenationEpsilon"); + allowed.push_back("concatenation"); + allowed.push_back("intersectionCartesian"); + allowed.push_back("iterationEpsilon"); + allowed.push_back("iteration"); + TCLAP::ValuesConstraint<std::string> allowedVals( allowed ); + + TCLAP::ValueArg<std::string> algorithm( "a", "algorithm", "Execute algorithm", true, "", &allowedVals); + cmd.add(algorithm); + + TCLAP::ValueArg<std::string> a1( "i", "input1", "First automaton", false, "-", "file"); + TCLAP::ValueArg<std::string> a2( "j", "input2", "Second automaton", false, "-", "file"); + cmd.add( a1 ); + cmd.add( a2 ); + + cmd.parse(argc,argv); + + std::list<sax::Token> a1Tokens, a2Tokens; + if(a1.isSet()) { + if(a1.getValue() == "-") { + sax::SaxParseInterface::parseStdin(a1Tokens); + } else { + sax::SaxParseInterface::parseFile(a1.getValue(), a1Tokens); + } + } else { + sax::SaxParseInterface::parseStdin(a1Tokens); + } + + if(a2.isSet()) { + if(a2.getValue() == "-") { + sax::SaxParseInterface::parseStdin(a2Tokens); + } else { + sax::SaxParseInterface::parseFile(a2.getValue(), a2Tokens); + } + } else if(algorithm.getValue() != "iteration" && algorithm.getValue() != "iterationEpsilon") { + sax::SaxParseInterface::parseStdin(a2Tokens); + } + + automaton::Automaton automaton1 = alib::DataFactory::fromTokens<automaton::Automaton>(a1Tokens); + + if( algorithm.getValue() == "unionEpsilon") { + automaton::Automaton automaton2 = alib::DataFactory::fromTokens<automaton::Automaton>(a2Tokens); + alib::DataFactory::toStdout(automaton::transform::AutomataUnionEpsilonTransition::unification(automaton1, automaton2)); + return 0; + } else if( algorithm.getValue() == "unionCartesian") { + automaton::Automaton automaton2 = alib::DataFactory::fromTokens<automaton::Automaton>(a2Tokens); + alib::DataFactory::toStdout(automaton::transform::AutomataUnionCartesianProduct::unification(automaton1, automaton2)); + return 0; + } else if( algorithm.getValue() == "concatenationEpsilon") { + automaton::Automaton automaton2 = alib::DataFactory::fromTokens<automaton::Automaton>(a2Tokens); + alib::DataFactory::toStdout(automaton::transform::AutomataConcatenationEpsilonTransition::concatenation(automaton1, automaton2)); + return 0; + } else if( algorithm.getValue() == "concatenation") { + automaton::Automaton automaton2 = alib::DataFactory::fromTokens<automaton::Automaton>(a2Tokens); + alib::DataFactory::toStdout(automaton::transform::AutomataConcatenation::concatenation(automaton1, automaton2)); + return 0; + } else if( algorithm.getValue() == "intersectionCartesian") { + automaton::Automaton automaton2 = alib::DataFactory::fromTokens<automaton::Automaton>(a2Tokens); + alib::DataFactory::toStdout(automaton::transform::AutomataIntersectionCartesianProduct::intersection(automaton1, automaton2)); + return 0; + } else if( algorithm.getValue() == "iteration") { + alib::DataFactory::toStdout(automaton::transform::AutomatonIteration::iteration(automaton1)); + return 0; + } else if( algorithm.getValue() == "iterationEpsilon") { + alib::DataFactory::toStdout(automaton::transform::AutomatonIterationEpsilonTransition::iteration(automaton1)); + return 0; + } else { + throw exception::AlibException( "Invalid algorithm" ); + return 1; + } + } catch( const exception::AlibException & exception ) { + alib::DataFactory::toStdout( exception ); + return 1; + } catch(const TCLAP::ArgException& exception) { + std::cout << exception.error() << std::endl; + return 2; + } catch (const std::exception& exception) { + std::cerr << "Exception caught: " << exception.what() << std::endl; + return 3; + } catch(...) { + std::cerr << "Unknown exception caught." << std::endl; + return 127; + } +} diff --git a/alib2algo/src/automaton/transform/AutomataConcatenation.cpp b/alib2algo/src/automaton/transform/AutomataConcatenation.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c8e3cdbec3fd115f56d6ef396ef795a97a75eca0 --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomataConcatenation.cpp @@ -0,0 +1,207 @@ +/* + * AutomataConcatenation.cpp + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#include "AutomataConcatenation.h" +#include <exception/AlibException.h> +#include <label/Label.h> +#include "common/PairLabel.h" + +#define AUTOMATON_FIRST (label::labelFrom(1)) +#define AUTOMATON_SECOND (label::labelFrom(2)) + +namespace automaton +{ + +namespace transform +{ + +automaton::Automaton AutomataConcatenation::concatenation(const automaton::Automaton& first, const automaton::Automaton& second) +{ + AutomatonBase* out; + Accept((void*) &out, first.getData(), second.getData(), AutomataConcatenation::AUTOMATA_CONCATENATION); + automaton::Automaton res(*out); + delete out; + return res; +} + +automaton::NFA AutomataConcatenation::concatenation(const automaton::NFA& first, const automaton::NFA& second) +{ + automaton::State q01q02(pairLabel(first.getInitialState(), second.getInitialState())); + automaton::NFA res(pairLabel(AUTOMATON_FIRST, first.getInitialState())); + + for(const auto& q : first.getStates()) + res.addState(pairLabel(AUTOMATON_FIRST, q)); + for(const auto& q : second.getStates()) + res.addState(pairLabel(AUTOMATON_SECOND, q)); + res.addState(q01q02); + + for(const auto& symbol : first.getInputAlphabet()) + res.addInputSymbol(symbol); + for(const auto& symbol : second.getInputAlphabet()) + res.addInputSymbol(symbol); + + if(first.getFinalStates().count(first.getInitialState()) > 0) + res.setInitialState(q01q02); + + for(const auto& t : first.getTransitions()) + { + for(const auto& q : t.second) + { + res.addTransition(pairLabel(AUTOMATON_FIRST, t.first.first), t.first.second, pairLabel(AUTOMATON_FIRST, q)); + + if(first.getFinalStates().count(q) > 0) + res.addTransition(pairLabel(AUTOMATON_FIRST, t.first.first), t.first.second, pairLabel(AUTOMATON_SECOND, second.getInitialState())); + } + } + for(const auto& t : second.getTransitions()) + for(const auto& q : t.second) + res.addTransition(pairLabel(AUTOMATON_SECOND, t.first.first), t.first.second, pairLabel(AUTOMATON_SECOND, q)); + + for(const auto& t : first.getTransitionsFromState(first.getInitialState())) + for(const auto& q : t.second) + res.addTransition(q01q02, t.first.second, pairLabel(AUTOMATON_FIRST, q)); + for(const auto& t : second.getTransitionsFromState(second.getInitialState())) + for(const auto& q : t.second) + res.addTransition(q01q02, t.first.second, pairLabel(AUTOMATON_SECOND, q)); + + for(const auto& q : second.getFinalStates()) + res.addFinalState(pairLabel(AUTOMATON_SECOND, q)); + if(first.getFinalStates().count(first.getInitialState()) > 0) + res.addFinalState(q01q02); + + return res; +} + +automaton::NFA AutomataConcatenation::concatenation(const automaton::DFA& first, const automaton::DFA& second) +{ + automaton::State q01q02(pairLabel(first.getInitialState(), second.getInitialState())); + automaton::NFA res(pairLabel(AUTOMATON_FIRST, first.getInitialState())); + + for(const auto& q : first.getStates()) + res.addState(pairLabel(AUTOMATON_FIRST, q)); + for(const auto& q : second.getStates()) + res.addState(pairLabel(AUTOMATON_SECOND, q)); + res.addState(q01q02); + + for(const auto& symbol : first.getInputAlphabet()) + res.addInputSymbol(symbol); + for(const auto& symbol : second.getInputAlphabet()) + res.addInputSymbol(symbol); + + if(first.getFinalStates().count(first.getInitialState()) > 0) + res.setInitialState(q01q02); + + for(const auto& t : first.getTransitions()) + { + res.addTransition(pairLabel(AUTOMATON_FIRST, t.first.first), t.first.second, pairLabel(AUTOMATON_FIRST, t.second)); + + if(first.getFinalStates().count(t.second) > 0) + res.addTransition(pairLabel(AUTOMATON_FIRST, t.first.first), t.first.second, pairLabel(AUTOMATON_SECOND, second.getInitialState())); + } + for(const auto& t : second.getTransitions()) + res.addTransition(pairLabel(AUTOMATON_SECOND, t.first.first), t.first.second, pairLabel(AUTOMATON_SECOND, t.second)); + + for(const auto& t : first.getTransitionsFromState(first.getInitialState())) + res.addTransition(q01q02, t.first.second, pairLabel(AUTOMATON_FIRST, t.second)); + for(const auto& t : second.getTransitionsFromState(second.getInitialState())) + res.addTransition(q01q02, t.first.second, pairLabel(AUTOMATON_SECOND, t.second)); + + for(const auto& q : second.getFinalStates()) + res.addFinalState(pairLabel(AUTOMATON_SECOND, q)); + if(first.getFinalStates().count(first.getInitialState()) > 0) + res.addFinalState(q01q02); + + return res; +} + +void AutomataConcatenation::Visit(void*, const automaton::EpsilonNFA&, const automaton::EpsilonNFA&) const +{ + throw exception::AlibException("Unsupported automaton type EpsilonNFA"); +} + +void AutomataConcatenation::Visit(void*, const automaton::CompactNFA&, const automaton::CompactNFA&) const +{ + throw exception::AlibException("Unsupported automaton type CompactNFA"); +} + +void AutomataConcatenation::Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomataConcatenation::concatenation(first, second)).plunder(); +} + +void AutomataConcatenation::Visit(void*, const automaton::ExtendedNFA&, const automaton::ExtendedNFA&) const +{ + throw exception::AlibException("Unsupported automaton type ExtendedNFA"); +} + +void AutomataConcatenation::Visit(void*, const automaton::MultiInitialStateNFA&, const automaton::MultiInitialStateNFA&) const +{ + throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA"); +} + +void AutomataConcatenation::Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomataConcatenation::concatenation(first, second)).plunder(); +} + +void AutomataConcatenation::Visit(void*, const automaton::DPDA&, const automaton::DPDA&) const +{ + throw exception::AlibException("Unsupported automaton type DPDA"); +} + +void AutomataConcatenation::Visit(void*, const automaton::NPDA&, const automaton::NPDA&) const +{ + throw exception::AlibException("Unsupported automaton type NPDA"); +} + +void AutomataConcatenation::Visit(void*, const automaton::InputDrivenNPDA&, const automaton::InputDrivenNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type InputDrivenNPDA"); +} + +void AutomataConcatenation::Visit(void*, const automaton::RealTimeHeightDeterministicDPDA&, const automaton::RealTimeHeightDeterministicDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA"); +} + +void AutomataConcatenation::Visit(void*, const automaton::RealTimeHeightDeterministicNPDA&, const automaton::RealTimeHeightDeterministicNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA"); +} + +void AutomataConcatenation::Visit(void*, const automaton::SinglePopNPDA&, const automaton::SinglePopNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type SinglePopNPDA"); +} + +void AutomataConcatenation::Visit(void*, const automaton::SinglePopDPDA&, const automaton::SinglePopDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type SinglePopDPDA"); +} + +void AutomataConcatenation::Visit(void*, const automaton::VisiblyPushdownDPDA&, const automaton::VisiblyPushdownDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA"); +} + +void AutomataConcatenation::Visit(void*, const automaton::VisiblyPushdownNPDA&, const automaton::VisiblyPushdownNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA"); +} + +void AutomataConcatenation::Visit(void*, const automaton::OneTapeDTM&, const automaton::OneTapeDTM&) const +{ + throw exception::AlibException("Unsupported automaton type OneTapeDTM"); +} + +const AutomataConcatenation AutomataConcatenation::AUTOMATA_CONCATENATION; + +} /* namespace transform */ + +} /* namespace automaton */ diff --git a/alib2algo/src/automaton/transform/AutomataConcatenation.h b/alib2algo/src/automaton/transform/AutomataConcatenation.h new file mode 100644 index 0000000000000000000000000000000000000000..9ee1b5523e20a2f73e0fc9a5a8f274420606425c --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomataConcatenation.h @@ -0,0 +1,59 @@ +/* + * AutomataConcatenation.h + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#ifndef AUTOMATA_CONCATENATION_H_ +#define AUTOMATA_CONCATENATION_H_ + +#include <automaton/Automaton.h> +#include <automaton/FSM/EpsilonNFA.h> + +namespace automaton +{ + +namespace transform +{ + +/** + * Concatenates two automata. + * - For finite automata A1, A2, we create automaton L accepting L(A1).L(A2) (Melichar, 2.78) + */ +class AutomataConcatenation : public automaton::VisitableAutomatonBase::const_promoting_visitor_type +{ +public: + static automaton::Automaton concatenation(const automaton::Automaton& first, const automaton::Automaton& second); + + static automaton::NFA concatenation(const automaton::DFA& first, const automaton::DFA& second); + static automaton::NFA concatenation(const automaton::NFA& first, const automaton::NFA& second); + +private: + void Visit(void* data, const automaton::CompactNFA& first, const automaton::CompactNFA& second) const; + void Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const; + void Visit(void* data, const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) const; + void Visit(void* data, const automaton::ExtendedNFA& first, const automaton::ExtendedNFA& second) const; + void Visit(void* data, const automaton::MultiInitialStateNFA& first, const automaton::MultiInitialStateNFA& second) const; + void Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const; + + void Visit(void* data, const automaton::DPDA& first, const automaton::DPDA& second) const; + void Visit(void* data, const automaton::NPDA& first, const automaton::NPDA& second) const; + void Visit(void* data, const automaton::InputDrivenNPDA& first, const automaton::InputDrivenNPDA& second) const; + void Visit(void* data, const automaton::RealTimeHeightDeterministicDPDA& first, const automaton::RealTimeHeightDeterministicDPDA& second) const; + void Visit(void* data, const automaton::RealTimeHeightDeterministicNPDA& first, const automaton::RealTimeHeightDeterministicNPDA& second) const; + void Visit(void* data, const automaton::SinglePopNPDA& first, const automaton::SinglePopNPDA& second) const; + void Visit(void* data, const automaton::SinglePopDPDA& first, const automaton::SinglePopDPDA& second) const; + void Visit(void* data, const automaton::VisiblyPushdownDPDA& first, const automaton::VisiblyPushdownDPDA& second) const; + void Visit(void* data, const automaton::VisiblyPushdownNPDA& first, const automaton::VisiblyPushdownNPDA& second) const; + + void Visit(void* data, const automaton::OneTapeDTM& first, const automaton::OneTapeDTM& second) const; + + static const AutomataConcatenation AUTOMATA_CONCATENATION; +}; + +} /* namespace transform */ + +} /* namespace automaton */ + +#endif /* AUTOMATA_CONCATENATION_H_ */ diff --git a/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.cpp b/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..199c99da24a805a2f5304213a0120ea5fc9d0086 --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.cpp @@ -0,0 +1,209 @@ +/* + * AutomataConcatenationEpsilonTransition.cpp + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#include "AutomataConcatenationEpsilonTransition.h" +#include <exception/AlibException.h> +#include <label/Label.h> +#include "common/PairLabel.h" + +#define AUTOMATON_FIRST 1 +#define AUTOMATON_SECOND 2 + +namespace automaton +{ + +namespace transform +{ + +automaton::Automaton AutomataConcatenationEpsilonTransition::concatenation(const automaton::Automaton& first, const automaton::Automaton& second) +{ + AutomatonBase* out; + Accept((void*) &out, first.getData(), second.getData(), AutomataConcatenationEpsilonTransition::AUTOMATA_CONCATENATION_EPSILON_TRANSITION); + automaton::Automaton res(*out); + delete out; + return res; +} + +automaton::EpsilonNFA AutomataConcatenationEpsilonTransition::concatenation(const automaton::DFA& first, const automaton::DFA& second) +{ + automaton::EpsilonNFA res(pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState())); + + for(const auto& symbol : first.getInputAlphabet()) + res.addInputSymbol(symbol); + for(const auto& symbol : second.getInputAlphabet()) + res.addInputSymbol(symbol); + + for(const auto& q : first.getStates()) + res.addState(pairLabel(label::labelFrom(AUTOMATON_FIRST), q)); + for(const auto& q : second.getStates()) + res.addState(pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + for(const auto& q : second.getFinalStates()) + res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + for(const auto& t : first.getTransitions()) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_FIRST), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_FIRST), t.second)); + + for(const auto& t : second.getTransitions()) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_SECOND), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_SECOND), t.second)); + + for(const auto& q : first.getFinalStates()) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_FIRST), q), pairLabel(label::labelFrom(AUTOMATON_SECOND), second.getInitialState())); + + return res; +} + +automaton::EpsilonNFA AutomataConcatenationEpsilonTransition::concatenation(const automaton::NFA& first, const automaton::NFA& second) +{ + automaton::EpsilonNFA res(pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState())); + + for(const auto& symbol : first.getInputAlphabet()) + res.addInputSymbol(symbol); + for(const auto& symbol : second.getInputAlphabet()) + res.addInputSymbol(symbol); + + for(const auto& q : first.getStates()) + res.addState(pairLabel(label::labelFrom(AUTOMATON_FIRST), q)); + for(const auto& q : second.getStates()) + res.addState(pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + for(const auto& q : second.getFinalStates()) + res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + for(const auto& t : first.getTransitions()) + for(const auto& q : t.second) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_FIRST), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_FIRST), q)); + + for(const auto& t : second.getTransitions()) + for(const auto& q : t.second) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_SECOND), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + for(const auto& q : first.getFinalStates()) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_FIRST), q), pairLabel(label::labelFrom(AUTOMATON_SECOND), second.getInitialState())); + + return res; +} + +automaton::EpsilonNFA AutomataConcatenationEpsilonTransition::concatenation(const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) +{ + automaton::EpsilonNFA res(pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState())); + + for(const auto& symbol : first.getInputAlphabet()) + res.addInputSymbol(symbol); + for(const auto& symbol : second.getInputAlphabet()) + res.addInputSymbol(symbol); + + for(const auto& q : first.getStates()) + res.addState(pairLabel(label::labelFrom(AUTOMATON_FIRST), q)); + for(const auto& q : second.getStates()) + res.addState(pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + for(const auto& q : second.getFinalStates()) + res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + for(const auto& t : first.getTransitions()) + for(const auto& q : t.second) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_FIRST), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_FIRST), q)); + + for(const auto& t : second.getTransitions()) + for(const auto& q : t.second) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_SECOND), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + for(const auto& q : first.getFinalStates()) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_FIRST), q), pairLabel(label::labelFrom(AUTOMATON_SECOND), second.getInitialState())); + + return res; +} + +void AutomataConcatenationEpsilonTransition::Visit(void* data, const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomataConcatenationEpsilonTransition::concatenation(first, second)).plunder(); +} + +void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::CompactNFA&, const automaton::CompactNFA&) const +{ + throw exception::AlibException("Unsupported automaton type CompactNFA"); +} + +void AutomataConcatenationEpsilonTransition::Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomataConcatenationEpsilonTransition::concatenation(first, second)).plunder(); +} + +void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::ExtendedNFA&, const automaton::ExtendedNFA&) const +{ + throw exception::AlibException("Unsupported automaton type ExtendedNFA"); +} + +void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::MultiInitialStateNFA&, const automaton::MultiInitialStateNFA&) const +{ + throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA"); +} + +void AutomataConcatenationEpsilonTransition::Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomataConcatenationEpsilonTransition::concatenation(first, second)).plunder(); +} + +void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::DPDA&, const automaton::DPDA&) const +{ + throw exception::AlibException("Unsupported automaton type DPDA"); +} + +void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::NPDA&, const automaton::NPDA&) const +{ + throw exception::AlibException("Unsupported automaton type NPDA"); +} + +void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::InputDrivenNPDA&, const automaton::InputDrivenNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type InputDrivenNPDA"); +} + +void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::RealTimeHeightDeterministicDPDA&, const automaton::RealTimeHeightDeterministicDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA"); +} + +void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::RealTimeHeightDeterministicNPDA&, const automaton::RealTimeHeightDeterministicNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA"); +} + +void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::SinglePopNPDA&, const automaton::SinglePopNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type SinglePopNPDA"); +} + +void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::SinglePopDPDA&, const automaton::SinglePopDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type SinglePopDPDA"); +} + +void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::VisiblyPushdownDPDA&, const automaton::VisiblyPushdownDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA"); +} + +void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::VisiblyPushdownNPDA&, const automaton::VisiblyPushdownNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA"); +} + +void AutomataConcatenationEpsilonTransition::Visit(void*, const automaton::OneTapeDTM&, const automaton::OneTapeDTM&) const +{ + throw exception::AlibException("Unsupported automaton type OneTapeDTM"); +} + +const AutomataConcatenationEpsilonTransition AutomataConcatenationEpsilonTransition::AUTOMATA_CONCATENATION_EPSILON_TRANSITION; + +} /* namespace transform */ + +} /* namespace automaton */ diff --git a/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h b/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h new file mode 100644 index 0000000000000000000000000000000000000000..b1c5c547030ba09746df2c123448edf93f30ba82 --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomataConcatenationEpsilonTransition.h @@ -0,0 +1,60 @@ +/* + * AutomataConcatenationEpsilonTransition.h + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#ifndef AUTOMATA_CONCATENATION_EPSILON_TRANSITION_H_ +#define AUTOMATA_CONCATENATION_EPSILON_TRANSITION_H_ + +#include <automaton/Automaton.h> +#include <automaton/FSM/EpsilonNFA.h> + +namespace automaton +{ + +namespace transform +{ + +/** + * Concatenates two automata. + * - For finite automata A1, A2, we create automaton L accepting L(A1).L(A2) + */ +class AutomataConcatenationEpsilonTransition : public automaton::VisitableAutomatonBase::const_promoting_visitor_type +{ +public: + static automaton::Automaton concatenation(const automaton::Automaton& first, const automaton::Automaton& second); + + static automaton::EpsilonNFA concatenation(const automaton::DFA& first, const automaton::DFA& second); + static automaton::EpsilonNFA concatenation(const automaton::NFA& first, const automaton::NFA& second); + static automaton::EpsilonNFA concatenation(const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second); + +private: + void Visit(void* data, const automaton::CompactNFA& first, const automaton::CompactNFA& second) const; + void Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const; + void Visit(void* data, const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) const; + void Visit(void* data, const automaton::ExtendedNFA& first, const automaton::ExtendedNFA& second) const; + void Visit(void* data, const automaton::MultiInitialStateNFA& first, const automaton::MultiInitialStateNFA& second) const; + void Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const; + + void Visit(void* data, const automaton::DPDA& first, const automaton::DPDA& second) const; + void Visit(void* data, const automaton::NPDA& first, const automaton::NPDA& second) const; + void Visit(void* data, const automaton::InputDrivenNPDA& first, const automaton::InputDrivenNPDA& second) const; + void Visit(void* data, const automaton::RealTimeHeightDeterministicDPDA& first, const automaton::RealTimeHeightDeterministicDPDA& second) const; + void Visit(void* data, const automaton::RealTimeHeightDeterministicNPDA& first, const automaton::RealTimeHeightDeterministicNPDA& second) const; + void Visit(void* data, const automaton::SinglePopNPDA& first, const automaton::SinglePopNPDA& second) const; + void Visit(void* data, const automaton::SinglePopDPDA& first, const automaton::SinglePopDPDA& second) const; + void Visit(void* data, const automaton::VisiblyPushdownDPDA& first, const automaton::VisiblyPushdownDPDA& second) const; + void Visit(void* data, const automaton::VisiblyPushdownNPDA& first, const automaton::VisiblyPushdownNPDA& second) const; + + void Visit(void* data, const automaton::OneTapeDTM& first, const automaton::OneTapeDTM& second) const; + + static const AutomataConcatenationEpsilonTransition AUTOMATA_CONCATENATION_EPSILON_TRANSITION; +}; + +} /* namespace transform */ + +} /* namespace automaton */ + +#endif /* AUTOMATA_CONCATENATION_EPSILON_H_ */ diff --git a/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.cpp b/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a287a18b3ca2c412e1b9097ed1b9948d8eb65de9 --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.cpp @@ -0,0 +1,182 @@ +/* + * AutomataIntersectionCartesianProduct.cpp + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#include "AutomataIntersectionCartesianProduct.h" +#include <exception/AlibException.h> +#include "common/PairLabel.h" + +#define AUTOMATON_FIRST 1 +#define AUTOMATON_SECOND 2 + +namespace automaton +{ + +namespace transform +{ + +automaton::Automaton AutomataIntersectionCartesianProduct::intersection(const automaton::Automaton& first, const automaton::Automaton& second) +{ + AutomatonBase* out; + Accept((void*) &out, first.getData(), second.getData(), AutomataIntersectionCartesianProduct::AUTOMATA_INTERSECTION_CARTESIAN_PRODUCT); + automaton::Automaton res(*out); + delete out; + return res; +} + +automaton::DFA AutomataIntersectionCartesianProduct::intersection(const automaton::DFA& first, const automaton::DFA& second) +{ + automaton::State q0(pairLabel(first.getInitialState(), second.getInitialState())); + automaton::DFA res(q0); + + for(const auto& a : first.getInputAlphabet()) + res.addInputSymbol(a); + for(const auto& a : second.getInputAlphabet()) + res.addInputSymbol(a); + + for(const auto& p : first.getStates()) + for(const auto& q : second.getStates()) + res.addState(automaton::State(pairLabel(p, q))); + + for(const auto& p : first.getFinalStates()) + for(const auto& q : second.getFinalStates()) + res.addFinalState(automaton::State(pairLabel(p, q))); + + for(const auto& state : res.getStates()) + { + const label::Label& label_p = static_cast<const label::LabelPairLabel&>(state.getName().getData()).getData().first; + const label::Label& label_q = static_cast<const label::LabelPairLabel&>(state.getName().getData()).getData().second; + + for(const auto& tp : first.getTransitionsFromState(automaton::State(label_p))) + for(const auto& tq : second.getTransitionsFromState(automaton::State(label_q))) + if(tp.first.second == tq.first.second) + res.addTransition(state, tp.first.second, automaton::State(pairLabel(tp.second, tq.second))); + } + + return res; +} + +automaton::NFA AutomataIntersectionCartesianProduct::intersection(const automaton::NFA& first, const automaton::NFA& second) +{ + automaton::State q0(pairLabel(first.getInitialState(), second.getInitialState())); + automaton::NFA res(q0); + + for(const auto& a : first.getInputAlphabet()) + res.addInputSymbol(a); + for(const auto& a : second.getInputAlphabet()) + res.addInputSymbol(a); + + for(const auto& p : first.getStates()) + for(const auto& q : second.getStates()) + res.addState(automaton::State(pairLabel(p, q))); + + for(const auto& p : first.getFinalStates()) + for(const auto& q : second.getFinalStates()) + res.addFinalState(automaton::State(pairLabel(p, q))); + + for(const auto& state : res.getStates()) + { + const label::Label& label_p = static_cast<const label::LabelPairLabel&>(state.getName().getData()).getData().first; + const label::Label& label_q = static_cast<const label::LabelPairLabel&>(state.getName().getData()).getData().second; + + for(const auto& tp : first.getTransitionsFromState(automaton::State(label_p))) + for(const auto& tq : second.getTransitionsFromState(automaton::State(label_q))) + if(tp.first.second == tq.first.second) + for(const auto& p : tp.second) + for(const auto& q : tq.second) + res.addTransition(state, tp.first.second, automaton::State(pairLabel(p, q))); + } + + return res; +} + +void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::EpsilonNFA&, const automaton::EpsilonNFA&) const +{ + throw exception::AlibException("Unsupported automaton type EpsilonNFA"); +} + +void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::CompactNFA&, const automaton::CompactNFA&) const +{ + throw exception::AlibException("Unsupported automaton type CompactNFA"); +} + +void AutomataIntersectionCartesianProduct::Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomataIntersectionCartesianProduct::intersection(first, second)).plunder(); +} + +void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::ExtendedNFA&, const automaton::ExtendedNFA&) const +{ + throw exception::AlibException("Unsupported automaton type ExtendedNFA"); +} + +void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::MultiInitialStateNFA&, const automaton::MultiInitialStateNFA&) const +{ + throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA"); +} + +void AutomataIntersectionCartesianProduct::Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomataIntersectionCartesianProduct::intersection(first, second)).plunder(); +} + +void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::DPDA&, const automaton::DPDA&) const +{ + throw exception::AlibException("Unsupported automaton type DPDA"); +} + +void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::NPDA&, const automaton::NPDA&) const +{ + throw exception::AlibException("Unsupported automaton type NPDA"); +} + +void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::InputDrivenNPDA&, const automaton::InputDrivenNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type InputDrivenNPDA"); +} + +void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::RealTimeHeightDeterministicDPDA&, const automaton::RealTimeHeightDeterministicDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA"); +} + +void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::RealTimeHeightDeterministicNPDA&, const automaton::RealTimeHeightDeterministicNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA"); +} + +void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::SinglePopNPDA&, const automaton::SinglePopNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type SinglePopNPDA"); +} + +void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::SinglePopDPDA&, const automaton::SinglePopDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type SinglePopDPDA"); +} + +void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::VisiblyPushdownDPDA&, const automaton::VisiblyPushdownDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA"); +} + +void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::VisiblyPushdownNPDA&, const automaton::VisiblyPushdownNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA"); +} + +void AutomataIntersectionCartesianProduct::Visit(void*, const automaton::OneTapeDTM&, const automaton::OneTapeDTM&) const +{ + throw exception::AlibException("Unsupported automaton type OneTapeDTM"); +} + +const AutomataIntersectionCartesianProduct AutomataIntersectionCartesianProduct::AUTOMATA_INTERSECTION_CARTESIAN_PRODUCT; + +} /* namespace transform */ + +} /* namespace automaton */ diff --git a/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.h b/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.h new file mode 100644 index 0000000000000000000000000000000000000000..2c00f01ea101221d630aa47c7e9578b4ff094c82 --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomataIntersectionCartesianProduct.h @@ -0,0 +1,59 @@ +/* + * AutomataIntersectionCartesianProduct.h + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#ifndef AUTOMATA_INTERSECTION_CARTESIAN_H_ +#define AUTOMATA_INTERSECTION_CARTESIAN_H_ + +#include <automaton/Automaton.h> +#include <automaton/FSM/EpsilonNFA.h> + +namespace automaton +{ + +namespace transform +{ + +/** + * Intersection of two automata. + * - For finite automata A1, A2, we create automaton L accepting L(A1) \cap L(A2) (Melichar, 2.75) + */ +class AutomataIntersectionCartesianProduct : public automaton::VisitableAutomatonBase::const_promoting_visitor_type +{ +public: + static automaton::Automaton intersection(const automaton::Automaton& first, const automaton::Automaton& second); + + static automaton::NFA intersection(const automaton::NFA& first, const automaton::NFA& second); + static automaton::DFA intersection(const automaton::DFA& first, const automaton::DFA& second); + +private: + void Visit(void* data, const automaton::CompactNFA& first, const automaton::CompactNFA& second) const; + void Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const; + void Visit(void* data, const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) const; + void Visit(void* data, const automaton::ExtendedNFA& first, const automaton::ExtendedNFA& second) const; + void Visit(void* data, const automaton::MultiInitialStateNFA& first, const automaton::MultiInitialStateNFA& second) const; + void Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const; + + void Visit(void* data, const automaton::DPDA& first, const automaton::DPDA& second) const; + void Visit(void* data, const automaton::NPDA& first, const automaton::NPDA& second) const; + void Visit(void* data, const automaton::InputDrivenNPDA& first, const automaton::InputDrivenNPDA& second) const; + void Visit(void* data, const automaton::RealTimeHeightDeterministicDPDA& first, const automaton::RealTimeHeightDeterministicDPDA& second) const; + void Visit(void* data, const automaton::RealTimeHeightDeterministicNPDA& first, const automaton::RealTimeHeightDeterministicNPDA& second) const; + void Visit(void* data, const automaton::SinglePopNPDA& first, const automaton::SinglePopNPDA& second) const; + void Visit(void* data, const automaton::SinglePopDPDA& first, const automaton::SinglePopDPDA& second) const; + void Visit(void* data, const automaton::VisiblyPushdownDPDA& first, const automaton::VisiblyPushdownDPDA& second) const; + void Visit(void* data, const automaton::VisiblyPushdownNPDA& first, const automaton::VisiblyPushdownNPDA& second) const; + + void Visit(void* data, const automaton::OneTapeDTM& first, const automaton::OneTapeDTM& second) const; + + static const AutomataIntersectionCartesianProduct AUTOMATA_INTERSECTION_CARTESIAN_PRODUCT; +}; + +} /* namespace transform */ + +} /* namespace automaton */ + +#endif /* AUTOMATA_INTERSECTION_CARTESIAN_H_ */ diff --git a/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.cpp b/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a03e1e1bf3bbe67d20e66ce2e2e5c338a903977 --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.cpp @@ -0,0 +1,196 @@ +/* + * AutomataUnionCartesianProduct.cpp + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#include "AutomataUnionCartesianProduct.h" +#include <exception/AlibException.h> +#include "common/PairLabel.h" + +#define AUTOMATON_FIRST 1 +#define AUTOMATON_SECOND 2 + +namespace automaton +{ + +namespace transform +{ + +automaton::Automaton AutomataUnionCartesianProduct::unification(const automaton::Automaton& first, const automaton::Automaton& second) +{ + AutomatonBase* out; + Accept((void*) &out, first.getData(), second.getData(), AutomataUnionCartesianProduct::AUTOMATA_UNION_CARTESIAN_PRODUCT); + automaton::Automaton res(*out); + delete out; + return res; +} + +automaton::DFA AutomataUnionCartesianProduct::unification(const automaton::DFA& first, const automaton::DFA& second) +{ + if(!first.isTotal() || !second.isTotal()) + throw exception::AlibException("Automata must be total to unify with cartesian product"); + + automaton::State q0(pairLabel(first.getInitialState(), second.getInitialState())); + automaton::DFA res(q0); + + for(const auto& a : first.getInputAlphabet()) + res.addInputSymbol(a); + for(const auto& a : second.getInputAlphabet()) + res.addInputSymbol(a); + + for(const auto& p : first.getStates()) + for(const auto& q : second.getStates()) + res.addState(automaton::State(pairLabel(p, q))); + + for(const auto& p : first.getFinalStates()) + for(const auto& q : second.getStates()) + res.addFinalState(automaton::State(pairLabel(p, q))); + + for(const auto& p : first.getStates()) + for(const auto& q : second.getFinalStates()) + res.addFinalState(automaton::State(pairLabel(p, q))); + + for(const auto& state : res.getStates()) + { + const label::Label& label_p = static_cast<const label::LabelPairLabel&>(state.getName().getData()).getData().first; + const label::Label& label_q = static_cast<const label::LabelPairLabel&>(state.getName().getData()).getData().second; + + for(const auto& tp : first.getTransitionsFromState(automaton::State(label_p))) + for(const auto& tq : second.getTransitionsFromState(automaton::State(label_q))) + if(tp.first.second == tq.first.second) + res.addTransition(state, tp.first.second, automaton::State(pairLabel(tp.second, tq.second))); + } + + return res; +} + +automaton::NFA AutomataUnionCartesianProduct::unification(const automaton::NFA& first, const automaton::NFA& second) +{ + if(!first.isTotal() || !second.isTotal()) + throw exception::AlibException("Automata must be total to unify with cartesian product"); + + automaton::State q0(pairLabel(first.getInitialState(), second.getInitialState())); + automaton::NFA res(q0); + + for(const auto& a : first.getInputAlphabet()) + res.addInputSymbol(a); + for(const auto& a : second.getInputAlphabet()) + res.addInputSymbol(a); + + for(const auto& p : first.getStates()) + for(const auto& q : second.getStates()) + res.addState(automaton::State(pairLabel(p, q))); + + for(const auto& p : first.getFinalStates()) + for(const auto& q : second.getStates()) + res.addFinalState(automaton::State(pairLabel(p, q))); + + for(const auto& p : first.getStates()) + for(const auto& q : second.getFinalStates()) + res.addFinalState(automaton::State(pairLabel(p, q))); + + for(const auto& state : res.getStates()) + { + const label::Label& label_p = static_cast<const label::LabelPairLabel&>(state.getName().getData()).getData().first; + const label::Label& label_q = static_cast<const label::LabelPairLabel&>(state.getName().getData()).getData().second; + + for(const auto& tp : first.getTransitionsFromState(automaton::State(label_p))) + for(const auto& tq : second.getTransitionsFromState(automaton::State(label_q))) + if(tp.first.second == tq.first.second) + for(const auto& p : tp.second) + for(const auto& q : tq.second) + res.addTransition(state, tp.first.second, automaton::State(pairLabel(p, q))); + } + + return res; +} + +void AutomataUnionCartesianProduct::Visit(void*, const automaton::EpsilonNFA&, const automaton::EpsilonNFA&) const +{ + throw exception::AlibException("Unsupported automaton type EpsilonNFA"); +} + +void AutomataUnionCartesianProduct::Visit(void*, const automaton::CompactNFA&, const automaton::CompactNFA&) const +{ + throw exception::AlibException("Unsupported automaton type CompactNFA"); +} + +void AutomataUnionCartesianProduct::Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomataUnionCartesianProduct::unification(first, second)).plunder(); +} + +void AutomataUnionCartesianProduct::Visit(void*, const automaton::ExtendedNFA&, const automaton::ExtendedNFA&) const +{ + throw exception::AlibException("Unsupported automaton type ExtendedNFA"); +} + +void AutomataUnionCartesianProduct::Visit(void*, const automaton::MultiInitialStateNFA&, const automaton::MultiInitialStateNFA&) const +{ + throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA"); +} + +void AutomataUnionCartesianProduct::Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomataUnionCartesianProduct::unification(first, second)).plunder(); +} + +void AutomataUnionCartesianProduct::Visit(void*, const automaton::DPDA&, const automaton::DPDA&) const +{ + throw exception::AlibException("Unsupported automaton type DPDA"); +} + +void AutomataUnionCartesianProduct::Visit(void*, const automaton::NPDA&, const automaton::NPDA&) const +{ + throw exception::AlibException("Unsupported automaton type NPDA"); +} + +void AutomataUnionCartesianProduct::Visit(void*, const automaton::InputDrivenNPDA&, const automaton::InputDrivenNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type InputDrivenNPDA"); +} + +void AutomataUnionCartesianProduct::Visit(void*, const automaton::RealTimeHeightDeterministicDPDA&, const automaton::RealTimeHeightDeterministicDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA"); +} + +void AutomataUnionCartesianProduct::Visit(void*, const automaton::RealTimeHeightDeterministicNPDA&, const automaton::RealTimeHeightDeterministicNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA"); +} + +void AutomataUnionCartesianProduct::Visit(void*, const automaton::SinglePopNPDA&, const automaton::SinglePopNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type SinglePopNPDA"); +} + +void AutomataUnionCartesianProduct::Visit(void*, const automaton::SinglePopDPDA&, const automaton::SinglePopDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type SinglePopDPDA"); +} + +void AutomataUnionCartesianProduct::Visit(void*, const automaton::VisiblyPushdownDPDA&, const automaton::VisiblyPushdownDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA"); +} + +void AutomataUnionCartesianProduct::Visit(void*, const automaton::VisiblyPushdownNPDA&, const automaton::VisiblyPushdownNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA"); +} + +void AutomataUnionCartesianProduct::Visit(void*, const automaton::OneTapeDTM&, const automaton::OneTapeDTM&) const +{ + throw exception::AlibException("Unsupported automaton type OneTapeDTM"); +} + +const AutomataUnionCartesianProduct AutomataUnionCartesianProduct::AUTOMATA_UNION_CARTESIAN_PRODUCT; + +} /* namespace transform */ + +} /* namespace automaton */ diff --git a/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.h b/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.h new file mode 100644 index 0000000000000000000000000000000000000000..305efabc5f7f082bcf9b98a4d322579f33181af3 --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomataUnionCartesianProduct.h @@ -0,0 +1,59 @@ +/* + * AutomataUnionCartesianProduct.h + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#ifndef AUTOMATA_UNION_CARTESIAN_H_ +#define AUTOMATA_UNION_CARTESIAN_H_ + +#include <automaton/Automaton.h> +#include <automaton/FSM/EpsilonNFA.h> + +namespace automaton +{ + +namespace transform +{ + +/** + * Union two automata. + * - For finite automata A1, A2, we create automaton L accepting L(A1) \cup L(A2) (Melichar, 2.71) + */ +class AutomataUnionCartesianProduct : public automaton::VisitableAutomatonBase::const_promoting_visitor_type +{ +public: + static automaton::Automaton unification(const automaton::Automaton& first, const automaton::Automaton& second); + + static automaton::NFA unification(const automaton::NFA& first, const automaton::NFA& second); + static automaton::DFA unification(const automaton::DFA& first, const automaton::DFA& second); + +private: + void Visit(void* data, const automaton::CompactNFA& first, const automaton::CompactNFA& second) const; + void Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const; + void Visit(void* data, const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) const; + void Visit(void* data, const automaton::ExtendedNFA& first, const automaton::ExtendedNFA& second) const; + void Visit(void* data, const automaton::MultiInitialStateNFA& first, const automaton::MultiInitialStateNFA& second) const; + void Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const; + + void Visit(void* data, const automaton::DPDA& first, const automaton::DPDA& second) const; + void Visit(void* data, const automaton::NPDA& first, const automaton::NPDA& second) const; + void Visit(void* data, const automaton::InputDrivenNPDA& first, const automaton::InputDrivenNPDA& second) const; + void Visit(void* data, const automaton::RealTimeHeightDeterministicDPDA& first, const automaton::RealTimeHeightDeterministicDPDA& second) const; + void Visit(void* data, const automaton::RealTimeHeightDeterministicNPDA& first, const automaton::RealTimeHeightDeterministicNPDA& second) const; + void Visit(void* data, const automaton::SinglePopNPDA& first, const automaton::SinglePopNPDA& second) const; + void Visit(void* data, const automaton::SinglePopDPDA& first, const automaton::SinglePopDPDA& second) const; + void Visit(void* data, const automaton::VisiblyPushdownDPDA& first, const automaton::VisiblyPushdownDPDA& second) const; + void Visit(void* data, const automaton::VisiblyPushdownNPDA& first, const automaton::VisiblyPushdownNPDA& second) const; + + void Visit(void* data, const automaton::OneTapeDTM& first, const automaton::OneTapeDTM& second) const; + + static const AutomataUnionCartesianProduct AUTOMATA_UNION_CARTESIAN_PRODUCT; +}; + +} /* namespace transform */ + +} /* namespace automaton */ + +#endif /* AUTOMATA_UNION_CARTESIAN_H_ */ diff --git a/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.cpp b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..848135ec651125cbf79921a4f98ee7ef0069b726 --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.cpp @@ -0,0 +1,229 @@ +/* + * AutomataUnionEpsilonTransition.cpp + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#include "AutomataUnionEpsilonTransition.h" +#include <exception/AlibException.h> +#include "common/PairLabel.h" + +#define AUTOMATON_FIRST 1 +#define AUTOMATON_SECOND 2 + +namespace automaton +{ + +namespace transform +{ + +automaton::Automaton AutomataUnionEpsilonTransition::unification(const automaton::Automaton& first, const automaton::Automaton& second) +{ + AutomatonBase* out; + Accept((void*) &out, first.getData(), second.getData(), AutomataUnionEpsilonTransition::AUTOMATA_UNION_EPSILON_TRANSITION); + automaton::Automaton res(*out); + delete out; + return res; +} + +automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) +{ + std::set<automaton::State> states; + for(const auto& q : first.getStates()) + states.insert(pairLabel(label::labelFrom(AUTOMATON_FIRST), q)); + for(const auto& q : second.getStates()) + states.insert(pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + automaton::State q0 = automaton::createUniqueState(automaton::State("q0"), states); + automaton::EpsilonNFA res(q0); + + for(const auto& a : first.getInputAlphabet()) + res.addInputSymbol(a); + for(const auto& a : second.getInputAlphabet()) + res.addInputSymbol(a); + + for(const auto& q : states) + res.addState(q); + + for(const auto& q : first.getFinalStates()) + res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_FIRST), q)); + for(const auto& q : second.getFinalStates()) + res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + res.addTransition(q0, pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState())); + res.addTransition(q0, pairLabel(label::labelFrom(AUTOMATON_SECOND), second.getInitialState())); + + for(const auto& t : first.getTransitions()) + for(const auto& q : t.second) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_FIRST), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_FIRST), q)); + + for(const auto& t : second.getTransitions()) + for(const auto& q : t.second) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_SECOND), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + return res; +} + +automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automaton::NFA& first, const automaton::NFA& second) +{ + std::set<automaton::State> states; + for(const auto& q : first.getStates()) + states.insert(pairLabel(label::labelFrom(AUTOMATON_FIRST), q)); + for(const auto& q : second.getStates()) + states.insert(pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + automaton::State q0 = automaton::createUniqueState(automaton::State("q0"), states); + automaton::EpsilonNFA res(q0); + + for(const auto& a : first.getInputAlphabet()) + res.addInputSymbol(a); + for(const auto& a : second.getInputAlphabet()) + res.addInputSymbol(a); + + for(const auto& q : states) + res.addState(q); + + for(const auto& q : first.getFinalStates()) + res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_FIRST), q)); + for(const auto& q : second.getFinalStates()) + res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + res.addTransition(q0, pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState())); + res.addTransition(q0, pairLabel(label::labelFrom(AUTOMATON_SECOND), second.getInitialState())); + + for(const auto& t : first.getTransitions()) + for(const auto& q : t.second) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_FIRST), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_FIRST), q)); + + for(const auto& t : second.getTransitions()) + for(const auto& q : t.second) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_SECOND), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + return res; +} + +automaton::EpsilonNFA AutomataUnionEpsilonTransition::unification(const automaton::DFA& first, const automaton::DFA& second) +{ + std::set<automaton::State> states; + for(const auto& q : first.getStates()) + states.insert(pairLabel(label::labelFrom(AUTOMATON_FIRST), q)); + for(const auto& q : second.getStates()) + states.insert(pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + automaton::State q0 = automaton::createUniqueState(automaton::State("q0"), states); + automaton::EpsilonNFA res(q0); + + for(const auto& a : first.getInputAlphabet()) + res.addInputSymbol(a); + for(const auto& a : second.getInputAlphabet()) + res.addInputSymbol(a); + + for(const auto& q : states) + res.addState(q); + + for(const auto& q : first.getFinalStates()) + res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_FIRST), q)); + for(const auto& q : second.getFinalStates()) + res.addFinalState(pairLabel(label::labelFrom(AUTOMATON_SECOND), q)); + + res.addTransition(q0, pairLabel(label::labelFrom(AUTOMATON_FIRST), first.getInitialState())); + res.addTransition(q0, pairLabel(label::labelFrom(AUTOMATON_SECOND), second.getInitialState())); + + for(const auto& t : first.getTransitions()) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_FIRST), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_FIRST), t.second)); + + for(const auto& t : second.getTransitions()) + res.addTransition(pairLabel(label::labelFrom(AUTOMATON_SECOND), t.first.first), t.first.second, pairLabel(label::labelFrom(AUTOMATON_SECOND), t.second)); + + return res; +} + +void AutomataUnionEpsilonTransition::Visit(void* data, const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomataUnionEpsilonTransition::unification(first, second)).plunder(); +} + +void AutomataUnionEpsilonTransition::Visit(void*, const automaton::CompactNFA&, const automaton::CompactNFA&) const +{ + throw exception::AlibException("Unsupported automaton type CompactNFA"); +} + +void AutomataUnionEpsilonTransition::Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomataUnionEpsilonTransition::unification(first, second)).plunder(); +} + +void AutomataUnionEpsilonTransition::Visit(void*, const automaton::ExtendedNFA&, const automaton::ExtendedNFA&) const +{ + throw exception::AlibException("Unsupported automaton type ExtendedNFA"); +} + +void AutomataUnionEpsilonTransition::Visit(void*, const automaton::MultiInitialStateNFA&, const automaton::MultiInitialStateNFA&) const +{ + throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA"); +} + +void AutomataUnionEpsilonTransition::Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomataUnionEpsilonTransition::unification(first, second)).plunder(); +} + +void AutomataUnionEpsilonTransition::Visit(void*, const automaton::DPDA&, const automaton::DPDA&) const +{ + throw exception::AlibException("Unsupported automaton type DPDA"); +} + +void AutomataUnionEpsilonTransition::Visit(void*, const automaton::NPDA&, const automaton::NPDA&) const +{ + throw exception::AlibException("Unsupported automaton type NPDA"); +} + +void AutomataUnionEpsilonTransition::Visit(void*, const automaton::InputDrivenNPDA&, const automaton::InputDrivenNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type InputDrivenNPDA"); +} + +void AutomataUnionEpsilonTransition::Visit(void*, const automaton::RealTimeHeightDeterministicDPDA&, const automaton::RealTimeHeightDeterministicDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA"); +} + +void AutomataUnionEpsilonTransition::Visit(void*, const automaton::RealTimeHeightDeterministicNPDA&, const automaton::RealTimeHeightDeterministicNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA"); +} + +void AutomataUnionEpsilonTransition::Visit(void*, const automaton::SinglePopNPDA&, const automaton::SinglePopNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type SinglePopNPDA"); +} + +void AutomataUnionEpsilonTransition::Visit(void*, const automaton::SinglePopDPDA&, const automaton::SinglePopDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type SinglePopDPDA"); +} + +void AutomataUnionEpsilonTransition::Visit(void*, const automaton::VisiblyPushdownDPDA&, const automaton::VisiblyPushdownDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA"); +} + +void AutomataUnionEpsilonTransition::Visit(void*, const automaton::VisiblyPushdownNPDA&, const automaton::VisiblyPushdownNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA"); +} + +void AutomataUnionEpsilonTransition::Visit(void*, const automaton::OneTapeDTM&, const automaton::OneTapeDTM&) const +{ + throw exception::AlibException("Unsupported automaton type OneTapeDTM"); +} + +const AutomataUnionEpsilonTransition AutomataUnionEpsilonTransition::AUTOMATA_UNION_EPSILON_TRANSITION; + +} /* namespace transform */ + +} /* namespace automaton */ diff --git a/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h new file mode 100644 index 0000000000000000000000000000000000000000..855fc5b94d9b4ffa067785c0b14a1f87a9a5a2a7 --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomataUnionEpsilonTransition.h @@ -0,0 +1,60 @@ +/* + * AutomataUnionEpsilonTransition.h + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#ifndef AUTOMATA_UNION_EPSILON_H_ +#define AUTOMATA_UNION_EPSILON_H_ + +#include <automaton/Automaton.h> +#include <automaton/FSM/EpsilonNFA.h> + +namespace automaton +{ + +namespace transform +{ + +/** + * Union two automata. + * - For finite automata A1, A2, we create automaton L accepting L(A1) \cup L(A2) + */ +class AutomataUnionEpsilonTransition : public automaton::VisitableAutomatonBase::const_promoting_visitor_type +{ +public: + static automaton::Automaton unification(const automaton::Automaton& first, const automaton::Automaton& second); + + static automaton::EpsilonNFA unification(const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second); + static automaton::EpsilonNFA unification(const automaton::NFA& first, const automaton::NFA& second); + static automaton::EpsilonNFA unification(const automaton::DFA& first, const automaton::DFA& second); + +private: + void Visit(void* data, const automaton::CompactNFA& first, const automaton::CompactNFA& second) const; + void Visit(void* data, const automaton::DFA& first, const automaton::DFA& second) const; + void Visit(void* data, const automaton::EpsilonNFA& first, const automaton::EpsilonNFA& second) const; + void Visit(void* data, const automaton::ExtendedNFA& first, const automaton::ExtendedNFA& second) const; + void Visit(void* data, const automaton::MultiInitialStateNFA& first, const automaton::MultiInitialStateNFA& second) const; + void Visit(void* data, const automaton::NFA& first, const automaton::NFA& second) const; + + void Visit(void* data, const automaton::DPDA& first, const automaton::DPDA& second) const; + void Visit(void* data, const automaton::NPDA& first, const automaton::NPDA& second) const; + void Visit(void* data, const automaton::InputDrivenNPDA& first, const automaton::InputDrivenNPDA& second) const; + void Visit(void* data, const automaton::RealTimeHeightDeterministicDPDA& first, const automaton::RealTimeHeightDeterministicDPDA& second) const; + void Visit(void* data, const automaton::RealTimeHeightDeterministicNPDA& first, const automaton::RealTimeHeightDeterministicNPDA& second) const; + void Visit(void* data, const automaton::SinglePopNPDA& first, const automaton::SinglePopNPDA& second) const; + void Visit(void* data, const automaton::SinglePopDPDA& first, const automaton::SinglePopDPDA& second) const; + void Visit(void* data, const automaton::VisiblyPushdownDPDA& first, const automaton::VisiblyPushdownDPDA& second) const; + void Visit(void* data, const automaton::VisiblyPushdownNPDA& first, const automaton::VisiblyPushdownNPDA& second) const; + + void Visit(void* data, const automaton::OneTapeDTM& first, const automaton::OneTapeDTM& second) const; + + static const AutomataUnionEpsilonTransition AUTOMATA_UNION_EPSILON_TRANSITION; +}; + +} /* namespace transform */ + +} /* namespace automaton */ + +#endif /* AUTOMATA_UNION_EPSILON_H_ */ diff --git a/alib2algo/src/automaton/transform/AutomatonIteration.cpp b/alib2algo/src/automaton/transform/AutomatonIteration.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad8dc7d4f1723d73db0d99f354c16d712a938296 --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomatonIteration.cpp @@ -0,0 +1,125 @@ +/* + * AutomatonIteration.cpp + * + * Created on: 29. 11. 2014 + * Author: Tomas Pecka + */ + +#include "AutomatonIteration.h" +#include <exception/AlibException.h> + +namespace automaton +{ + +namespace transform +{ + +automaton::Automaton AutomatonIteration::iteration(const automaton::Automaton& automaton) +{ + AutomatonBase* out; + automaton.getData().Accept((void*) &out, AutomatonIteration::AUTOMATON_ITERATION); + automaton::Automaton res(*out); + delete out; + return res; +} + +template<class T> +automaton::NFA AutomatonIteration::iteration(const T& automaton) +{ + automaton::NFA res(automaton); + + for(const auto& qf : res.getFinalStates()) + for(const auto& t : res.getTransitionsToState(qf)) + res.addTransition(t.first.first, t.first.second, res.getInitialState()); + + res.addFinalState(automaton.getInitialState()); + return res; +} + +void AutomatonIteration::Visit(void*, const automaton::EpsilonNFA&) const +{ + throw exception::AlibException("Unsupported automaton type EpsilonNFA"); +} + +void AutomatonIteration::Visit(void*, const automaton::CompactNFA&) const +{ + throw exception::AlibException("Unsupported automaton type CompactNFA"); +} + +void AutomatonIteration::Visit(void* data, const automaton::DFA& automaton) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomatonIteration::iteration(automaton)).plunder(); +} + +void AutomatonIteration::Visit(void*, const automaton::ExtendedNFA&) const +{ + throw exception::AlibException("Unsupported automaton type ExtendedNFA"); +} + +void AutomatonIteration::Visit(void*, const automaton::MultiInitialStateNFA&) const +{ + throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA"); +} + +void AutomatonIteration::Visit(void* data, const automaton::NFA& automaton) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomatonIteration::iteration(automaton)).plunder(); +} + +void AutomatonIteration::Visit(void*, const automaton::DPDA&) const +{ + throw exception::AlibException("Unsupported automaton type DPDA"); +} + +void AutomatonIteration::Visit(void*, const automaton::NPDA&) const +{ + throw exception::AlibException("Unsupported automaton type NPDA"); +} + +void AutomatonIteration::Visit(void*, const automaton::InputDrivenNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type InputDrivenNPDA"); +} + +void AutomatonIteration::Visit(void*, const automaton::RealTimeHeightDeterministicDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA"); +} + +void AutomatonIteration::Visit(void*, const automaton::RealTimeHeightDeterministicNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA"); +} + +void AutomatonIteration::Visit(void*, const automaton::SinglePopNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type SinglePopNPDA"); +} + +void AutomatonIteration::Visit(void*, const automaton::SinglePopDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type SinglePopDPDA"); +} + +void AutomatonIteration::Visit(void*, const automaton::VisiblyPushdownDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA"); +} + +void AutomatonIteration::Visit(void*, const automaton::VisiblyPushdownNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA"); +} + +void AutomatonIteration::Visit(void*, const automaton::OneTapeDTM&) const +{ + throw exception::AlibException("Unsupported automaton type OneTapeDTM"); +} + +const AutomatonIteration AutomatonIteration::AUTOMATON_ITERATION; + +} /* namespace transform */ + +} /* namespace automaton */ diff --git a/alib2algo/src/automaton/transform/AutomatonIteration.h b/alib2algo/src/automaton/transform/AutomatonIteration.h new file mode 100644 index 0000000000000000000000000000000000000000..e19861e088ecc80d8944f4325493a13c7d766b31 --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomatonIteration.h @@ -0,0 +1,59 @@ +/* + * AutomatonIteration.h + * + * Created on: 29. 11. 2014 + * Author: Tomas Pecka + */ + +#ifndef AUTOMATON_ITERATION_H_ +#define AUTOMATON_ITERATION_H_ + +#include <automaton/Automaton.h> +#include <automaton/FSM/EpsilonNFA.h> + +namespace automaton +{ + +namespace transform +{ + +/** + * Iterates language given by automaton + * - For finite automaton A1, we create automaton L accepting L(A1)* + */ +class AutomatonIteration : public automaton::VisitableAutomatonBase::const_visitor_type +{ +public: + static automaton::Automaton iteration(const automaton::Automaton& automaton); + + template<class T> + static automaton::NFA iteration(const T& automaton); + +private: + void Visit(void* data, const automaton::CompactNFA& automaton) const; + void Visit(void* data, const automaton::DFA& automaton) const; + void Visit(void* data, const automaton::EpsilonNFA& automaton) const; + void Visit(void* data, const automaton::ExtendedNFA& automaton) const; + void Visit(void* data, const automaton::MultiInitialStateNFA& automaton) const; + void Visit(void* data, const automaton::NFA& automaton) const; + + void Visit(void* data, const automaton::DPDA& automaton) const; + void Visit(void* data, const automaton::NPDA& automaton) const; + void Visit(void* data, const automaton::InputDrivenNPDA& automaton) const; + void Visit(void* data, const automaton::RealTimeHeightDeterministicDPDA& automaton) const; + void Visit(void* data, const automaton::RealTimeHeightDeterministicNPDA& automaton) const; + void Visit(void* data, const automaton::SinglePopNPDA& automaton) const; + void Visit(void* data, const automaton::SinglePopDPDA& automaton) const; + void Visit(void* data, const automaton::VisiblyPushdownDPDA& automaton) const; + void Visit(void* data, const automaton::VisiblyPushdownNPDA& automaton) const; + + void Visit(void* data, const automaton::OneTapeDTM& automaton) const; + + static const AutomatonIteration AUTOMATON_ITERATION; +}; + +} /* namespace transform */ + +} /* namespace automaton */ + +#endif /* AUTOMATON_ITERATION_H_ */ diff --git a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6cf3b6a1a90dbc7b53eb5449dca7054eef524ba2 --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.cpp @@ -0,0 +1,125 @@ +/* + * AutomatonIterationEpsilonTransition.cpp + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#include "AutomatonIterationEpsilonTransition.h" +#include <exception/AlibException.h> + +namespace automaton +{ + +namespace transform +{ + +automaton::Automaton AutomatonIterationEpsilonTransition::iteration(const automaton::Automaton& automaton) +{ + AutomatonBase* out; + automaton.getData().Accept((void*) &out, AutomatonIterationEpsilonTransition::AUTOMATON_ITERATION_EPSILON_TRANSITION); + automaton::Automaton res(*out); + delete out; + return res; +} + +template<class T> +automaton::EpsilonNFA AutomatonIterationEpsilonTransition::iteration(const T& automaton) +{ + automaton::EpsilonNFA res(automaton); + + for(const auto&q : automaton.getFinalStates()) + res.addTransition(q, automaton.getInitialState()); + + res.addFinalState(automaton.getInitialState()); + return res; +} + +void AutomatonIterationEpsilonTransition::Visit(void* data, const automaton::EpsilonNFA& automaton) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomatonIterationEpsilonTransition::iteration(automaton)).plunder(); +} + +void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::CompactNFA&) const +{ + throw exception::AlibException("Unsupported automaton type CompactNFA"); +} + +void AutomatonIterationEpsilonTransition::Visit(void* data, const automaton::DFA& automaton) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomatonIterationEpsilonTransition::iteration(automaton)).plunder(); +} + +void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::ExtendedNFA&) const +{ + throw exception::AlibException("Unsupported automaton type ExtendedNFA"); +} + +void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::MultiInitialStateNFA&) const +{ + throw exception::AlibException("Unsupported automaton type MultiInitialStateNFA"); +} + +void AutomatonIterationEpsilonTransition::Visit(void* data, const automaton::NFA& automaton) const +{ + AutomatonBase* &ret = *(AutomatonBase**) data; + ret = std::move(AutomatonIterationEpsilonTransition::iteration(automaton)).plunder(); +} + +void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::DPDA&) const +{ + throw exception::AlibException("Unsupported automaton type DPDA"); +} + +void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::NPDA&) const +{ + throw exception::AlibException("Unsupported automaton type NPDA"); +} + +void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::InputDrivenNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type InputDrivenNPDA"); +} + +void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::RealTimeHeightDeterministicDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicDPDA"); +} + +void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::RealTimeHeightDeterministicNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type RealTimeHeightDeterministicNPDA"); +} + +void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::SinglePopNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type SinglePopNPDA"); +} + +void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::SinglePopDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type SinglePopDPDA"); +} + +void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::VisiblyPushdownDPDA&) const +{ + throw exception::AlibException("Unsupported automaton type VisiblyPushdownDPDA"); +} + +void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::VisiblyPushdownNPDA&) const +{ + throw exception::AlibException("Unsupported automaton type VisiblyPushdownNPDA"); +} + +void AutomatonIterationEpsilonTransition::Visit(void*, const automaton::OneTapeDTM&) const +{ + throw exception::AlibException("Unsupported automaton type OneTapeDTM"); +} + +const AutomatonIterationEpsilonTransition AutomatonIterationEpsilonTransition::AUTOMATON_ITERATION_EPSILON_TRANSITION; + +} /* namespace transform */ + +} /* namespace automaton */ diff --git a/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h new file mode 100644 index 0000000000000000000000000000000000000000..7329e8cfb50fdb8ce60fdf0c1033f4e18a89c53f --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomatonIterationEpsilonTransition.h @@ -0,0 +1,59 @@ +/* + * AutomatonIterationEpsilonTransition.h + * + * Created on: 29. 11. 2014 + * Author: Tomas Pecka + */ + +#ifndef AUTOMATON_ITERATION_EPSILON_TRANSITION_H_ +#define AUTOMATON_ITERATION_EPSILON_TRANSITION_H_ + +#include <automaton/Automaton.h> +#include <automaton/FSM/EpsilonNFA.h> + +namespace automaton +{ + +namespace transform +{ + +/** + * Iterates language given by automaton + * - For finite automaton A1, we create automaton L accepting L(A1)* + */ +class AutomatonIterationEpsilonTransition : public automaton::VisitableAutomatonBase::const_visitor_type +{ +public: + static automaton::Automaton iteration(const automaton::Automaton& automaton); + + template<class T> + static automaton::EpsilonNFA iteration(const T& automaton); + +private: + void Visit(void* data, const automaton::CompactNFA& automaton) const; + void Visit(void* data, const automaton::DFA& automaton) const; + void Visit(void* data, const automaton::EpsilonNFA& automaton) const; + void Visit(void* data, const automaton::ExtendedNFA& automaton) const; + void Visit(void* data, const automaton::MultiInitialStateNFA& automaton) const; + void Visit(void* data, const automaton::NFA& automaton) const; + + void Visit(void* data, const automaton::DPDA& automaton) const; + void Visit(void* data, const automaton::NPDA& automaton) const; + void Visit(void* data, const automaton::InputDrivenNPDA& automaton) const; + void Visit(void* data, const automaton::RealTimeHeightDeterministicDPDA& automaton) const; + void Visit(void* data, const automaton::RealTimeHeightDeterministicNPDA& automaton) const; + void Visit(void* data, const automaton::SinglePopNPDA& automaton) const; + void Visit(void* data, const automaton::SinglePopDPDA& automaton) const; + void Visit(void* data, const automaton::VisiblyPushdownDPDA& automaton) const; + void Visit(void* data, const automaton::VisiblyPushdownNPDA& automaton) const; + + void Visit(void* data, const automaton::OneTapeDTM& automaton) const; + + static const AutomatonIterationEpsilonTransition AUTOMATON_ITERATION_EPSILON_TRANSITION; +}; + +} /* namespace transform */ + +} /* namespace automaton */ + +#endif /* AUTOMATON_ITERATION_EPSILON_H_ */ diff --git a/alib2algo/src/automaton/transform/common/PairLabel.cpp b/alib2algo/src/automaton/transform/common/PairLabel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..76b42064854024030afd54da44d2e7ce6bbc3198 --- /dev/null +++ b/alib2algo/src/automaton/transform/common/PairLabel.cpp @@ -0,0 +1,26 @@ +/* + * PairLabel.cpp + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#include "PairLabel.h" + +namespace automaton { + +namespace transform { + +automaton::State pairLabel(const label::Label& first, const automaton::State& second) +{ + return automaton::State(label::Label(label::LabelPairLabel(std::make_pair(first, second.getName())))); +} + +automaton::State pairLabel(const automaton::State& first, const automaton::State& second) +{ + return automaton::State(label::Label(label::LabelPairLabel(std::make_pair(first.getName(), second.getName())))); +} + +} /* namespace transform */ + +} /* namespace automaton */ diff --git a/alib2algo/src/automaton/transform/common/PairLabel.h b/alib2algo/src/automaton/transform/common/PairLabel.h new file mode 100644 index 0000000000000000000000000000000000000000..ed2e334d54d622d61d5fbf995e14bd5d82e5740a --- /dev/null +++ b/alib2algo/src/automaton/transform/common/PairLabel.h @@ -0,0 +1,25 @@ +/* + * PairLabel.h + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#ifndef PAIR_LABEL_H_ +#define PAIR_LABEL_H_ + +#include <automaton/common/State.h> +#include <label/LabelPairLabel.h> + +namespace automaton { + +namespace transform { + +automaton::State pairLabel(const label::Label& first, const automaton::State& second); +automaton::State pairLabel(const automaton::State& first, const automaton::State& second); + +} /* namespace transform */ + +} /* namespace automaton */ + +#endif /* PAIR_LABEL_H_ */ diff --git a/alib2algo/test-src/automaton/transform/AutomataConcatenationTest.cpp b/alib2algo/test-src/automaton/transform/AutomataConcatenationTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4acd4ed33f15b9ab84b94f63db15b691436d3200 --- /dev/null +++ b/alib2algo/test-src/automaton/transform/AutomataConcatenationTest.cpp @@ -0,0 +1,87 @@ +#include <list> +#include "AutomataConcatenationTest.h" + +#include "automaton/transform/AutomataConcatenation.h" +#include "automaton/transform/AutomataConcatenationEpsilonTransition.h" + +#include "automaton/simplify/MinimizeBrzozowski.h" +#include "automaton/simplify/Normalize.h" +#include "automaton/simplify/EpsilonRemover.h" +#include "automaton/simplify/Trim.h" +#include "automaton/simplify/Total.h" +#include "automaton/determinize/Determinize.h" + +#include <factory/DataFactory.hpp> + +#define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y)) + +CPPUNIT_TEST_SUITE_REGISTRATION( AutomataConcatenationTest ); + +void AutomataConcatenationTest::setUp() { +} + +void AutomataConcatenationTest::tearDown() { +} + +void AutomataConcatenationTest::testAutomataConcatenation() { + // based on Melichar, 2.79 + + automaton::State q1a("1"), q2a("2"), q0a("0"), q1b("1'"), q2b("2'"), q0b("0'"); + automaton::State q0102("q0102"); + alphabet::Symbol a(alphabet::symbolFrom('a')), b(alphabet::symbolFrom('b')); + + automaton::DFA m1(q1a); + automaton::DFA m2(q1b); + automaton::NFA m3(q1a); + + m1.setInputSymbols({a, b}); + m1.setStates({q1a, q2a, q0a}); + m1.addTransition(q1a, a, q2a); + m1.addTransition(q1a, b, q0a); + m1.addTransition(q2a, a, q2a); + m1.addTransition(q2a, b, q0a); + m1.addTransition(q0a, a, q0a); + m1.addTransition(q0a, b, q0a); + m1.addFinalState(q2a); + + m2.setInputSymbols({a, b}); + m2.setStates({q1b, q2b}); + m2.addTransition(q1b, b, q2b); + m2.addTransition(q2b, b, q2b); + m2.addFinalState(q2b); + + m3.setInputSymbols({a, b}); + m3.setStates({q1a, q1b, q2a, q2b, q0a, q0b, q0102}); + m3.addTransition(q1a, a, q2a); + m3.addTransition(q1a, a, q1b); + m3.addTransition(q1a, b, q0a); + m3.addTransition(q2a, a, q2a); + m3.addTransition(q2a, a, q1b); + m3.addTransition(q2a, b, q0a); + m3.addTransition(q0a, a, q0a); + m3.addTransition(q0a, b, q0a); + m3.addTransition(q1b, a, q0b); + m3.addTransition(q1b, b, q2b); + m3.addTransition(q2b, a, q0b); + m3.addTransition(q2b, b, q2b); + m3.addTransition(q0b, a, q0b); + m3.addTransition(q0b, b, q0b); + m3.setFinalStates({q2b}); + + auto u11 = automaton::transform::AutomataConcatenationEpsilonTransition::concatenation(automaton::Automaton(automaton::DFA(m1)), automaton::Automaton(automaton::NFA(m2))); + auto u12 = automaton::transform::AutomataConcatenationEpsilonTransition::concatenation(automaton::Automaton(automaton::DFA(m1)), automaton::Automaton(automaton::DFA(m2))); + auto u21 = automaton::transform::AutomataConcatenation::concatenation(automaton::Automaton(automaton::DFA(m1)), automaton::Automaton(automaton::NFA(m2))); + auto u22 = automaton::transform::AutomataConcatenation::concatenation(automaton::Automaton(automaton::DFA(m1)), automaton::Automaton(automaton::DFA(m2))); + + automaton::Automaton umdfa (automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemover::remove(m3))))); + automaton::Automaton umdfa11(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemover::remove(u11))))); + automaton::Automaton umdfa12(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemover::remove(u12))))); + automaton::Automaton umdfa21(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemover::remove(u21))))); + automaton::Automaton umdfa22(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemover::remove(u22))))); + + CPPUNIT_ASSERT(umdfa11 == umdfa); + CPPUNIT_ASSERT(umdfa12 == umdfa); + CPPUNIT_ASSERT(umdfa21 == umdfa); + CPPUNIT_ASSERT(umdfa22 == umdfa); + +} diff --git a/alib2algo/test-src/automaton/transform/AutomataConcatenationTest.h b/alib2algo/test-src/automaton/transform/AutomataConcatenationTest.h new file mode 100644 index 0000000000000000000000000000000000000000..aa7dbecb205d1ff070f96c0498dce44fa3946343 --- /dev/null +++ b/alib2algo/test-src/automaton/transform/AutomataConcatenationTest.h @@ -0,0 +1,19 @@ +#ifndef AUTOMATA_CONCAT_TEST_H_ +#define AUTOMATA_CONCAT_TEST_H_ + +#include <cppunit/extensions/HelperMacros.h> + +class AutomataConcatenationTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( AutomataConcatenationTest ); + CPPUNIT_TEST( testAutomataConcatenation ); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp(); + void tearDown(); + + void testAutomataConcatenation(); +}; + +#endif /* AUTOMATA_CONCAT_TEST_H_ */ diff --git a/alib2algo/test-src/automaton/transform/AutomataUnionTest.cpp b/alib2algo/test-src/automaton/transform/AutomataUnionTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe6d35161b8214812a9806bf673f8919f905581f --- /dev/null +++ b/alib2algo/test-src/automaton/transform/AutomataUnionTest.cpp @@ -0,0 +1,76 @@ +#include <list> +#include "AutomataUnionTest.h" + +#include "automaton/transform/AutomataUnionCartesianProduct.h" +#include "automaton/transform/AutomataUnionEpsilonTransition.h" +#include "automaton/simplify/MinimizeBrzozowski.h" +#include "automaton/simplify/Normalize.h" +#include "automaton/simplify/EpsilonRemover.h" +#include "automaton/simplify/Trim.h" +#include "automaton/simplify/Total.h" +#include "automaton/determinize/Determinize.h" + +#include <factory/DataFactory.hpp> + +#define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y)) + +CPPUNIT_TEST_SUITE_REGISTRATION( AutomataUnionTest ); + +void AutomataUnionTest::setUp() { +} + +void AutomataUnionTest::tearDown() { +} + +void AutomataUnionTest::testAutomataUnion() { + // based on Melichar, 2.72 + + automaton::State q1a("1"), q2a("2"), q0a("0"), q1b("1'"), q2b("2'"), q0b("0'"); + automaton::State q11("11"), q20("20"), q00("00"), q02("02"); + alphabet::Symbol a(alphabet::symbolFrom('a')), b(alphabet::symbolFrom('b')); + + automaton::DFA m1(q1a); + automaton::DFA m2(q1b); + automaton::DFA m3(q11); + + m1.setInputSymbols({a, b}); + m1.setStates({q1a, q2a, q0a}); + m1.addTransition(q1a, a, q2a); + m1.addTransition(q1a, b, q0a); + m1.addTransition(q2a, a, q2a); + m1.addTransition(q2a, b, q0a); + m1.addTransition(q0a, a, q0a); + m1.addTransition(q0a, b, q0a); + m1.addFinalState(q2a); + + m2.setInputSymbols({a, b}); + m2.setStates({q1b, q2b}); + m2.addTransition(q1b, b, q2b); + m2.addTransition(q2b, b, q2b); + m2.addFinalState(q2b); + + m3.setInputSymbols({a, b}); + m3.setStates({q11, q20, q00, q02}); + m3.addTransition(q11, a, q20); + m3.addTransition(q11, b, q02); + m3.addTransition(q20, a, q20); + m3.addTransition(q20, b, q00); + m3.addTransition(q00, a, q00); + m3.addTransition(q00, b, q00); + m3.addTransition(q02, a, q00); + m3.addTransition(q02, b, q02); + m3.setFinalStates({q20, q02}); + + auto u1 = automaton::transform::AutomataUnionEpsilonTransition::unification(automaton::Automaton(m1), automaton::Automaton(m2)); + CPPUNIT_ASSERT_THROW(automaton::transform::AutomataUnionCartesianProduct::unification(automaton::Automaton(m1), automaton::Automaton(m2)), exception::AlibException); + CPPUNIT_ASSERT_THROW(automaton::transform::AutomataUnionCartesianProduct::unification(automaton::Automaton(automaton::NFA(m1)), automaton::Automaton(m2)), exception::AlibException); + auto u2 = automaton::transform::AutomataUnionEpsilonTransition::unification(automaton::Automaton(automaton::simplify::Total::total(m1)), automaton::Automaton(automaton::simplify::Total::total(m2))); + + automaton::Automaton umdfa(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemover::remove(m3))))); + automaton::Automaton umdfa1(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemover::remove(u1))))); + automaton::Automaton umdfa2(automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemover::remove(u2))))); + + CPPUNIT_ASSERT(umdfa1 == umdfa); + CPPUNIT_ASSERT(umdfa2 == umdfa); + +} diff --git a/alib2algo/test-src/automaton/transform/AutomataUnionTest.h b/alib2algo/test-src/automaton/transform/AutomataUnionTest.h new file mode 100644 index 0000000000000000000000000000000000000000..d45ef404d8ee8f8996ef4079d6d8e1de1dbb9890 --- /dev/null +++ b/alib2algo/test-src/automaton/transform/AutomataUnionTest.h @@ -0,0 +1,19 @@ +#ifndef AUTOMATA_UNION_TEST_H_ +#define AUTOMATA_UNION_TEST_H_ + +#include <cppunit/extensions/HelperMacros.h> + +class AutomataUnionTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( AutomataUnionTest ); + CPPUNIT_TEST( testAutomataUnion ); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp(); + void tearDown(); + + void testAutomataUnion(); +}; + +#endif /* AUTOMATA_UNION_TEST_H_ */ diff --git a/alib2algo/test-src/automaton/transform/AutomatonIterationTest.cpp b/alib2algo/test-src/automaton/transform/AutomatonIterationTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae36365ddaff7a84b2678e7e5579e4abae3194b2 --- /dev/null +++ b/alib2algo/test-src/automaton/transform/AutomatonIterationTest.cpp @@ -0,0 +1,58 @@ +#include <list> +#include "AutomatonIterationTest.h" + +#include "automaton/transform/AutomatonIteration.h" +#include "automaton/transform/AutomatonIterationEpsilonTransition.h" + +#include "automaton/simplify/MinimizeBrzozowski.h" +#include "automaton/simplify/Normalize.h" +#include "automaton/simplify/EpsilonRemover.h" +#include "automaton/simplify/Trim.h" +#include "automaton/simplify/Total.h" +#include "automaton/determinize/Determinize.h" + +#include <factory/DataFactory.hpp> + +#define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y)) + +CPPUNIT_TEST_SUITE_REGISTRATION( AutomatonIterationTest ); + +void AutomatonIterationTest::setUp() { +} + +void AutomatonIterationTest::tearDown() { +} + +void AutomatonIterationTest::testAutomatonIteration() { + + // Melichar 2.83 + automaton::State q1(1), q2(2), q3(3); + alphabet::Symbol a(alphabet::symbolFrom('a')), b(alphabet::symbolFrom('b')); + + automaton::DFA m1(q1); + m1.setStates({q1, q2, q3}); + m1.addFinalState(q3); + m1.setInputSymbols({a, b}); + m1.addTransition(q1, a, q2); + m1.addTransition(q2, b, q2); + m1.addTransition(q2, a, q3); + + automaton::NFA res(q1); + res.setStates({q1, q2, q3}); + res.setInputSymbols({a, b}); + res.setFinalStates({q1, q3}); + res.addTransition(q1, a, q2); + res.addTransition(q2, b, q2); + res.addTransition(q2, a, q3); + res.addTransition(q2, a, q1); + + automaton::Automaton i2 = automaton::transform::AutomatonIterationEpsilonTransition::iteration(automaton::Automaton(m1)); + automaton::Automaton i1 = automaton::transform::AutomatonIteration::iteration(automaton::Automaton(m1)); + + automaton::Automaton mdfa1 (automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemover::remove(i1))))); + automaton::Automaton mdfa2 (automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemover::remove(i2))))); + automaton::Automaton mdfa3 (automaton::simplify::Normalize::normalize(automaton::simplify::Trim::trim(automaton::simplify::MinimizeBrzozowski::minimize(automaton::simplify::EpsilonRemover::remove(res))))); + + CPPUNIT_ASSERT(mdfa1 == mdfa2); + CPPUNIT_ASSERT(mdfa1 == mdfa3); +} diff --git a/alib2algo/test-src/automaton/transform/AutomatonIterationTest.h b/alib2algo/test-src/automaton/transform/AutomatonIterationTest.h new file mode 100644 index 0000000000000000000000000000000000000000..28119050acdb90a63d8b8ebd524739c0b58ba364 --- /dev/null +++ b/alib2algo/test-src/automaton/transform/AutomatonIterationTest.h @@ -0,0 +1,19 @@ +#ifndef AUTOMATA_ITER_TEST_H_ +#define AUTOMATA_ITER_TEST_H_ + +#include <cppunit/extensions/HelperMacros.h> + +class AutomatonIterationTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE( AutomatonIterationTest ); + CPPUNIT_TEST( testAutomatonIteration ); + CPPUNIT_TEST_SUITE_END(); + +public: + void setUp(); + void tearDown(); + + void testAutomatonIteration(); +}; + +#endif /* AUTOMATA_ITER_TEST_H_ */ diff --git a/makefile b/makefile index 5a2044bc2bf0e4b9b62c951e440219cb2a395e94..a7efa5c1a5b973de046b89dcd0b9580dd7a6195d 100644 --- a/makefile +++ b/makefile @@ -12,6 +12,7 @@ SUBDIRS_BINS = acat2 \ adiff2 \ aepsilon2 \ aintegral2 \ + alangop2 \ aminimize2 \ anormalize2 \ arand2 \