diff --git a/alib2/src/automaton/AutomatonBase.cpp b/alib2/src/automaton/AutomatonBase.cpp index 0c73ea6fbba2da17f087b2bb9f5cede3064d52dd..5f0b45eb22048c18fcc69a7bbea7d9966044ff5f 100644 --- a/alib2/src/automaton/AutomatonBase.cpp +++ b/alib2/src/automaton/AutomatonBase.cpp @@ -41,7 +41,11 @@ bool AutomatonBase::operator==(const ExtendedNFA&) const { return false; } -bool AutomatonBase::operator==(const PDA&) const { +bool AutomatonBase::operator==(const NPDA&) const { + return false; +} + +bool AutomatonBase::operator==(const SinglePopNPDA&) const { return false; } diff --git a/alib2/src/automaton/AutomatonBase.h b/alib2/src/automaton/AutomatonBase.h index cc2b51e4b7a077309ce0b4ed5076fc0b17ead2f0..4038de9f78f8acf44ecfbc88cc05bc6d9589232d 100644 --- a/alib2/src/automaton/AutomatonBase.h +++ b/alib2/src/automaton/AutomatonBase.h @@ -19,13 +19,14 @@ class NFA; class EpsilonNFA; class CompactNFA; class ExtendedNFA; -class PDA; +class NPDA; +class SinglePopNPDA; class OneTapeDTM; /** * Abstract base class for all automata. */ -class AutomatonBase : public std::elementBase<UnknownAutomaton, DFA, NFA, EpsilonNFA, CompactNFA, ExtendedNFA, PDA, OneTapeDTM> { +class AutomatonBase : public std::elementBase<UnknownAutomaton, DFA, NFA, EpsilonNFA, CompactNFA, ExtendedNFA, NPDA, SinglePopNPDA, OneTapeDTM> { public: virtual AutomatonBase* clone() const = 0; @@ -47,7 +48,9 @@ public: virtual bool operator==(const ExtendedNFA& other) const; - virtual bool operator==(const PDA& other) const; + virtual bool operator==(const NPDA& other) const; + + virtual bool operator==(const SinglePopNPDA& other) const; virtual bool operator==(const OneTapeDTM& other) const; diff --git a/alib2/src/automaton/AutomatonFeatures.h b/alib2/src/automaton/AutomatonFeatures.h index d31ff4d00496fa51a1445fe012084be1b9828753..9d2b9f875196b5f38dcae15bd44f659c89a56a24 100644 --- a/alib2/src/automaton/AutomatonFeatures.h +++ b/alib2/src/automaton/AutomatonFeatures.h @@ -17,7 +17,8 @@ enum class FEATURES { DFA, COMPACT_NFA, EXTENDED_NFA, - PDA, + NPDA, + SINGLE_POP_NDPA, ONE_TAPE_TM }; diff --git a/alib2/src/automaton/AutomatonFromXMLParser.cpp b/alib2/src/automaton/AutomatonFromXMLParser.cpp index fb92ceafd2f73c06d2f5c0e57e43b232e688b8d4..0f8cd0f6011d4b7b2d1a3f8bf9a6a19aa99b114b 100644 --- a/alib2/src/automaton/AutomatonFromXMLParser.cpp +++ b/alib2/src/automaton/AutomatonFromXMLParser.cpp @@ -18,7 +18,7 @@ namespace automaton { Automaton AutomatonFromXMLParser::parse(std::list<sax::Token> &input) const { - return parse(input, std::set<FEATURES>({FEATURES::AUTOMATON, FEATURES::EPSILON_NFA, FEATURES::NFA, FEATURES::DFA, FEATURES::COMPACT_NFA, FEATURES::EXTENDED_NFA, FEATURES::PDA, FEATURES::ONE_TAPE_TM})); + return parse(input, std::set<FEATURES>({FEATURES::AUTOMATON, FEATURES::EPSILON_NFA, FEATURES::NFA, FEATURES::DFA, FEATURES::COMPACT_NFA, FEATURES::EXTENDED_NFA, FEATURES::NPDA, FEATURES::SINGLE_POP_NDPA, FEATURES::ONE_TAPE_TM})); } Automaton AutomatonFromXMLParser::parse(std::list<sax::Token>& input, const std::set<FEATURES>& features) const { diff --git a/alib2/src/automaton/AutomatonToXMLComposer.cpp b/alib2/src/automaton/AutomatonToXMLComposer.cpp index f6ed517a74273293e4fe4ce8b9986164996d6b7d..f4ea9fe7b00a80dbba73cdbbc5d290b4bdbdb689 100644 --- a/alib2/src/automaton/AutomatonToXMLComposer.cpp +++ b/alib2/src/automaton/AutomatonToXMLComposer.cpp @@ -329,7 +329,12 @@ std::list<sax::Token> AutomatonToXMLComposer::compose(const CompactNFA& automato return out; } -std::list<sax::Token> AutomatonToXMLComposer::compose(const PDA& automaton) const { +std::list<sax::Token> AutomatonToXMLComposer::compose(const NPDA& automaton) const { + std::list<sax::Token> out; + return out; +} + +std::list<sax::Token> AutomatonToXMLComposer::compose(const SinglePopNPDA& automaton) const { std::list<sax::Token> out; return out; } @@ -374,7 +379,11 @@ void AutomatonToXMLComposer::Visit(void* data, const CompactNFA& automaton) cons *((std::list<sax::Token>*) data) = this->compose(automaton); } -void AutomatonToXMLComposer::Visit(void* data, const PDA& automaton) const { +void AutomatonToXMLComposer::Visit(void* data, const NPDA& automaton) const { + *((std::list<sax::Token>*) data) = this->compose(automaton); +} + +void AutomatonToXMLComposer::Visit(void* data, const SinglePopNPDA& automaton) const { *((std::list<sax::Token>*) data) = this->compose(automaton); } diff --git a/alib2/src/automaton/AutomatonToXMLComposer.h b/alib2/src/automaton/AutomatonToXMLComposer.h index b9e1687af4c89e4baa3f94a1c387a1c70f036839..23fdd43d880a8addb97cf28d1af05760c0851e91 100644 --- a/alib2/src/automaton/AutomatonToXMLComposer.h +++ b/alib2/src/automaton/AutomatonToXMLComposer.h @@ -30,7 +30,8 @@ class AutomatonToXMLComposer : public AutomatonBase::const_visitor_type { void Visit(void*, const DFA& automaton) const; void Visit(void*, const ExtendedNFA& automaton) const; void Visit(void*, const CompactNFA& automaton) const; - void Visit(void*, const PDA& automaton) const; + void Visit(void*, const NPDA& automaton) const; + void Visit(void*, const SinglePopNPDA& automaton) const; void Visit(void*, const OneTapeDTM& automaton) const; protected: @@ -76,7 +77,8 @@ public: std::list<sax::Token> compose(const EpsilonNFA& automaton) const; std::list<sax::Token> compose(const ExtendedNFA& automaton) const; std::list<sax::Token> compose(const CompactNFA& automaton) const; - std::list<sax::Token> compose(const PDA& automaton) const; + std::list<sax::Token> compose(const NPDA& automaton) const; + std::list<sax::Token> compose(const SinglePopNPDA& automaton) const; std::list<sax::Token> compose(const OneTapeDTM& automaton) const; }; diff --git a/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.cpp b/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.cpp index f5128e778c8314b5e85ab6d307ea04cd7b72d393..fab84651eff0ed57e4c93fa7d0fbfc5ba7de88d8 100644 --- a/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.cpp +++ b/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.cpp @@ -190,7 +190,11 @@ void FiniteAutomatonToStringComposer::Visit(void*, const CompactNFA&) const { throw exception::AlibException(); } -void FiniteAutomatonToStringComposer::Visit(void*, const PDA&) const { +void FiniteAutomatonToStringComposer::Visit(void*, const NPDA&) const { + throw exception::AlibException(); +} + +void FiniteAutomatonToStringComposer::Visit(void*, const SinglePopNPDA&) const { throw exception::AlibException(); } diff --git a/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.h b/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.h index cacb27ec64c93b32622d89a88416f81728cad297..32e7332210d8d19f1fd61a199c00bca191eba993 100644 --- a/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.h +++ b/alib2/src/automaton/FSM/FiniteAutomatonToStringComposer.h @@ -17,7 +17,8 @@ class FiniteAutomatonToStringComposer : public AutomatonBase::const_visitor_type void Visit(void*, const DFA& automaton) const; void Visit(void*, const ExtendedNFA& automaton) const; void Visit(void*, const CompactNFA& automaton) const; - void Visit(void*, const PDA& automaton) const; + void Visit(void*, const NPDA& automaton) const; + void Visit(void*, const SinglePopNPDA& automaton) const; void Visit(void*, const OneTapeDTM& automaton) const; void composeTransitionsFromState(std::stringstream& out, const DFA& automaton, const State& from) const; diff --git a/alib2/src/automaton/PDA/PDA.cpp b/alib2/src/automaton/PDA/NPDA.cpp similarity index 82% rename from alib2/src/automaton/PDA/PDA.cpp rename to alib2/src/automaton/PDA/NPDA.cpp index f4a6ab35b3320acfb07cd7dd16b7f5878aa28414..49eda1d1acef31b1a048b7f0a11d56bd72a71c42 100644 --- a/alib2/src/automaton/PDA/PDA.cpp +++ b/alib2/src/automaton/PDA/NPDA.cpp @@ -1,26 +1,26 @@ /* - * PDA.cpp + * NPDA.cpp * * Created on: Apr 10, 2013 * Author: martin */ -#include "PDA.h" +#include "NPDA.h" #include "../../std/map.hpp" #include "../AutomatonException.h" #include <algorithm> namespace automaton { -AutomatonBase* PDA::clone() const { - return new PDA(*this); +AutomatonBase* NPDA::clone() const { + return new NPDA(*this); } -AutomatonBase* PDA::plunder() && { - return new PDA(std::move(*this)); +AutomatonBase* NPDA::plunder() && { + return new NPDA(std::move(*this)); } -bool PDA::removeState(const State& state) { +bool NPDA::removeState(const State& state) { if (initialStates.find(state) != initialStates.end()) { throw AutomatonException("State \"" + (std::string) state.getName() + "\" is initial state."); } @@ -41,7 +41,7 @@ bool PDA::removeState(const State& state) { return states.erase(state); } -bool PDA::removeInputSymbol(const alphabet::Symbol& symbol) { +bool NPDA::removeInputSymbol(const alphabet::Symbol& symbol) { for (std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >::const_iterator transition = transitions.begin(); transition != transitions.end(); transition++) { if (std::get<1>(transition->first).is<alphabet::Symbol>() && symbol == std::get<1>(transition->first).get<alphabet::Symbol>()) throw AutomatonException("Symbol \"" + (std::string) symbol + "\" is used in transition."); @@ -50,11 +50,11 @@ bool PDA::removeInputSymbol(const alphabet::Symbol& symbol) { return inputAlphabet.erase(symbol); } -bool PDA::addStackSymbol(const alphabet::Symbol& symbol) { +bool NPDA::addStackSymbol(const alphabet::Symbol& symbol) { return stackAlphabet.insert(symbol).second; } -void PDA::setStackSymbols(const std::set<alphabet::Symbol>& newSymbols) { +void NPDA::setStackSymbols(const std::set<alphabet::Symbol>& newSymbols) { std::set<alphabet::Symbol> removed; std::set_difference(stackAlphabet.begin(), stackAlphabet.end(), newSymbols.begin(), newSymbols.end(), std::inserter(removed, removed.end())); @@ -70,7 +70,7 @@ void PDA::setStackSymbols(const std::set<alphabet::Symbol>& newSymbols) { } } -bool PDA::removeStackSymbol(const alphabet::Symbol& symbol) { +bool NPDA::removeStackSymbol(const alphabet::Symbol& symbol) { for (std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >::const_iterator transition = transitions.begin(); transition != transitions.end(); transition++) { for (std::vector<alphabet::Symbol>::const_iterator popSymbol = std::get<2>(transition->first).begin(); popSymbol != std::get<2>(transition->first).end(); popSymbol++) { @@ -90,11 +90,11 @@ bool PDA::removeStackSymbol(const alphabet::Symbol& symbol) { return stackAlphabet.erase(symbol); } -const std::set<alphabet::Symbol>& PDA::getStackAlphabet() const { +const std::set<alphabet::Symbol>& NPDA::getStackAlphabet() const { return stackAlphabet; } -bool PDA::addTransition(const State& from, const alphabet::Symbol& input, const std::vector<alphabet::Symbol> pop, const State& to, const std::vector<alphabet::Symbol> push) { +bool NPDA::addTransition(const State& from, const alphabet::Symbol& input, const std::vector<alphabet::Symbol>& pop, const State& to, const std::vector<alphabet::Symbol>& push) { if (states.find(from) == states.end()) { throw AutomatonException("State \"" + (std::string) from.getName() + "\" doesn't exist."); } @@ -128,7 +128,7 @@ bool PDA::addTransition(const State& from, const alphabet::Symbol& input, const return transitions[key].insert(value).second; } -bool PDA::removeTransition(const State& from, const alphabet::Symbol& input, const std::vector<alphabet::Symbol> pop, const State& to, const std::vector<alphabet::Symbol> push) { +bool NPDA::removeTransition(const State& from, const alphabet::Symbol& input, const std::vector<alphabet::Symbol>& pop, const State& to, const std::vector<alphabet::Symbol>& push) { std::variant<string::Epsilon, alphabet::Symbol> inputVariant; inputVariant.set<alphabet::Symbol>(input); std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> > key(from, inputVariant, pop); @@ -138,11 +138,11 @@ bool PDA::removeTransition(const State& from, const alphabet::Symbol& input, con return transitions[key].erase(value); } -const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >& PDA::getTransitions() const { +const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >& NPDA::getTransitions() const { return transitions; } -bool PDA::addInitialSymbol(const alphabet::Symbol& start) { +bool NPDA::addInitialSymbol(const alphabet::Symbol& start) { if (stackAlphabet.find(start) == stackAlphabet.end()) { throw AutomatonException("Stack symbol \"" + (std::string) start + "\" doesn't exist."); } @@ -150,11 +150,11 @@ bool PDA::addInitialSymbol(const alphabet::Symbol& start) { return this->initialSymbols.insert(start).second; } -bool PDA::removeInitialSymbol(const alphabet::Symbol& start) { +bool NPDA::removeInitialSymbol(const alphabet::Symbol& start) { return this->initialSymbols.erase(start); } -void PDA::setInitialSymbols(const std::set<alphabet::Symbol>& symbols) { +void NPDA::setInitialSymbols(const std::set<alphabet::Symbol>& symbols) { std::set<alphabet::Symbol> tmp; std::set_difference(symbols.begin(), symbols.end(), this->stackAlphabet.begin(), this->stackAlphabet.end(), std::inserter(tmp, tmp.end())); if(tmp.size() != 0) @@ -163,20 +163,20 @@ void PDA::setInitialSymbols(const std::set<alphabet::Symbol>& symbols) { this->initialSymbols = symbols; } -const std::set<alphabet::Symbol>& PDA::getInitialSymbols() const { +const std::set<alphabet::Symbol>& NPDA::getInitialSymbols() const { return initialSymbols; } -bool PDA::operator==(const AutomatonBase& other) const { +bool NPDA::operator==(const AutomatonBase& other) const { return other == *this; } -bool PDA::operator==(const PDA& other) const { +bool NPDA::operator==(const NPDA& other) const { return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialStates == other.initialStates && this->finalStates == other.finalStates && this->stackAlphabet == other.stackAlphabet && this->initialSymbols == other.initialSymbols && this->transitions == other.transitions; } -void PDA::operator>>(std::ostream& out) const { - out << "(PDA" +void NPDA::operator>>(std::ostream& out) const { + out << "(NPDA" << "states = " << states << "inputAlphabet = " << inputAlphabet << "initialStates = " << initialStates diff --git a/alib2/src/automaton/PDA/PDA.h b/alib2/src/automaton/PDA/NPDA.h similarity index 82% rename from alib2/src/automaton/PDA/PDA.h rename to alib2/src/automaton/PDA/NPDA.h index ca03be482dd35d02b7d5901fe5be6785bf46e00b..dd7912bd61b292570a607757efb0ef89224f4942 100644 --- a/alib2/src/automaton/PDA/PDA.h +++ b/alib2/src/automaton/PDA/NPDA.h @@ -1,12 +1,12 @@ /* - * PDA.h + * NPDA.h * * Created on: Apr 10, 2013 * Author: martin */ -#ifndef PDA_H_ -#define PDA_H_ +#ifndef NPDA_H_ +#define NPDA_H_ #include <set> #include <map> @@ -23,7 +23,7 @@ namespace automaton { /** * Push Down Automaton */ -class PDA: public std::element<PDA, AutomatonBase>, public MultiInitialStates, public InputAlphabet { +class NPDA: public std::element<NPDA, AutomatonBase>, public MultiInitialStates, public InputAlphabet { protected: std::set<alphabet::Symbol> stackAlphabet; std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::pair<State, std::vector<alphabet::Symbol> > > > transitions; @@ -72,28 +72,28 @@ public: const std::set<alphabet::Symbol>& getStackAlphabet() const; /** - * Adds transition to the PDA. + * Adds transition to the NPDA. * @param transition transition to add * @throws AutomatonException when some part of the transition is not present - * in the PDA (state, input symbol, stack symbol) or when transition already exists + * in the NPDA (state, input symbol, stack symbol) or when transition already exists */ - bool addTransition(const State& from, const alphabet::Symbol& input, const std::vector<alphabet::Symbol> pop, const State& to, const std::vector<alphabet::Symbol> push); + bool addTransition(const State& from, const alphabet::Symbol& input, const std::vector<alphabet::Symbol>& pop, const State& to, const std::vector<alphabet::Symbol>& push); /** - * Removes the transition from the PDA. + * Removes the transition from the NPDA. * @param transition transition to remove - * @throws AutomatonException when transition is not present in the PDA + * @throws AutomatonException when transition is not present in the NPDA */ - bool removeTransition(const State& from, const alphabet::Symbol& input, const std::vector<alphabet::Symbol> pop, const State& to, const std::vector<alphabet::Symbol> push); + bool removeTransition(const State& from, const alphabet::Symbol& input, const std::vector<alphabet::Symbol>& pop, const State& to, const std::vector<alphabet::Symbol>& push); /** - * @return PDA transitions + * @return NPDA transitions */ const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >& getTransitions() const; /** * Adds initial symbol. Initial symbols are symbols that are pushed - * to the stack when PDA is created. + * to the stack when NPDA is created. * @param start new initial symbol * @throws AutomatonException when symbol is not present in the stack alphabet or it is already in the set */ @@ -102,7 +102,7 @@ public: /** * Adds initial symbol. Initial symbols are symbols that are pushed - * to the stack when PDA is created. + * to the stack when NPDA is created. * @param start new initial symbol * @throws AutomatonException when symbol is not present in the set of initial symbols */ @@ -110,7 +110,7 @@ public: /** * Sets initial symbols. Initial symbols are symbols that are pushed - * to the stack when PDA is created. + * to the stack when NPDA is created. * @param symbols new initial symbols * @throws AutomatonException when any of symbols is not present in the stack alphabet */ @@ -123,7 +123,7 @@ public: virtual bool operator==(const AutomatonBase& other) const; - virtual bool operator==(const PDA& other) const; + virtual bool operator==(const NPDA& other) const; virtual void operator>>(std::ostream& os) const; @@ -131,4 +131,4 @@ public: } /* namespace automaton */ -#endif /* PDA_H_ */ +#endif /* NPDA_H_ */ diff --git a/alib2/src/automaton/PDA/SinglePopNPDA.cpp b/alib2/src/automaton/PDA/SinglePopNPDA.cpp new file mode 100644 index 0000000000000000000000000000000000000000..826e9ea0e0ccb8170c35ff9e19840fe4b37f9916 --- /dev/null +++ b/alib2/src/automaton/PDA/SinglePopNPDA.cpp @@ -0,0 +1,186 @@ +/* + * SinglePopNPDA.cpp + * + * Created on: Apr 10, 2013 + * Author: martin + */ + +#include "SinglePopNPDA.h" +#include "../../std/map.hpp" +#include "../AutomatonException.h" +#include <algorithm> + +namespace automaton { + +AutomatonBase* SinglePopNPDA::clone() const { + return new SinglePopNPDA(*this); +} + +AutomatonBase* SinglePopNPDA::plunder() && { + return new SinglePopNPDA(std::move(*this)); +} + +bool SinglePopNPDA::removeState(const State& state) { + if (initialStates.find(state) != initialStates.end()) { + throw AutomatonException("State \"" + (std::string) state.getName() + "\" is initial state."); + } + + if (finalStates.find(state) != finalStates.end()) { + throw AutomatonException("State \"" + (std::string) state.getName() + "\" is final state."); + } + + for (std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol>, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >::const_iterator transition = transitions.begin(); transition != transitions.end(); transition++) { + if (state == std::get<0>(transition->first)) + throw AutomatonException("State \"" + (std::string) state.getName() + "\" is used in transition."); + for(std::set<std::pair<State, std::vector<alphabet::Symbol> > >::iterator target = transition->second.begin(); target != transition->second.end(); target++) { + if(target->first == state) + throw AutomatonException("State \"" + (std::string) state.getName() + "\" is used in transition."); + } + } + + return states.erase(state); +} + +bool SinglePopNPDA::removeInputSymbol(const alphabet::Symbol& symbol) { + for (std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol>, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >::const_iterator transition = transitions.begin(); transition != transitions.end(); transition++) { + if (std::get<1>(transition->first).is<alphabet::Symbol>() && symbol == std::get<1>(transition->first).get<alphabet::Symbol>()) + throw AutomatonException("Symbol \"" + (std::string) symbol + "\" is used in transition."); + } + + return inputAlphabet.erase(symbol); +} + +bool SinglePopNPDA::addStackSymbol(const alphabet::Symbol& symbol) { + return stackAlphabet.insert(symbol).second; +} + +void SinglePopNPDA::setStackSymbols(const std::set<alphabet::Symbol>& newSymbols) { + std::set<alphabet::Symbol> removed; + std::set_difference(stackAlphabet.begin(), stackAlphabet.end(), newSymbols.begin(), newSymbols.end(), std::inserter(removed, removed.end())); + + std::set<alphabet::Symbol> added; + std::set_difference(newSymbols.begin(), newSymbols.end(), stackAlphabet.begin(), stackAlphabet.end(), std::inserter(added, added.end())); + + for(const alphabet::Symbol& removedSymbol : removed) { + removeStackSymbol(removedSymbol); + } + + for(const alphabet::Symbol& addedSymbol : added) { + addStackSymbol(addedSymbol); + } +} + +bool SinglePopNPDA::removeStackSymbol(const alphabet::Symbol& symbol) { + for (std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol>, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >::const_iterator transition = transitions.begin(); transition != transitions.end(); transition++) { + if (symbol == std::get<2>(transition->first)) + throw AutomatonException("Stack symbol \"" + (std::string) symbol + "\" is used in transition."); + + for (std::set<std::pair<State, std::vector<alphabet::Symbol> > >::const_iterator target = transition->second.begin(); target != transition->second.end(); target++) { + if (std::find(target->second.begin(), target->second.end(), symbol) != target->second.end()) + throw AutomatonException("Stack symbol \"" + (std::string) symbol + "\" is used in transition."); + } + } + + if(initialSymbols.find(symbol) != initialSymbols.end()) { + throw AutomatonException("Stack symbol \"" + (std::string) symbol + "\" is start symbol."); + } + + return stackAlphabet.erase(symbol); +} + +const std::set<alphabet::Symbol>& SinglePopNPDA::getStackAlphabet() const { + return stackAlphabet; +} + +bool SinglePopNPDA::addTransition(const State& from, const alphabet::Symbol& input, const alphabet::Symbol& pop, const State& to, const std::vector<alphabet::Symbol>& push) { + if (states.find(from) == states.end()) { + throw AutomatonException("State \"" + (std::string) from.getName() + "\" doesn't exist."); + } + + if (inputAlphabet.find(input) == inputAlphabet.end()) { + throw AutomatonException("Input symbol \"" + (std::string) input + "\" doesn't exist."); + } + + if (states.find(to) == states.end()) { + throw AutomatonException("State \"" + (std::string) to.getName() + "\" doesn't exist."); + } + + if (stackAlphabet.find(pop) == stackAlphabet.end()) { + throw AutomatonException("Stack symbol \"" + (std::string) pop + "\" doesn't exist."); + } + + for(std::vector<alphabet::Symbol>::const_iterator pushSymbol = push.begin(); pushSymbol != push.end(); pushSymbol++) { + if (stackAlphabet.find(*pushSymbol) == stackAlphabet.end()) { + throw AutomatonException("Stack symbol \"" + (std::string) *pushSymbol + "\" doesn't exist."); + } + } + + std::variant<string::Epsilon, alphabet::Symbol> inputVariant; + inputVariant.set<alphabet::Symbol>(input); + std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol> key(from, inputVariant, pop); + + std::pair<automaton::State, std::vector<alphabet::Symbol> > value = std::make_pair(to, push); + + return transitions[key].insert(value).second; +} + +bool SinglePopNPDA::removeTransition(const State& from, const alphabet::Symbol& input, const alphabet::Symbol& pop, const State& to, const std::vector<alphabet::Symbol>& push) { + std::variant<string::Epsilon, alphabet::Symbol> inputVariant; + inputVariant.set<alphabet::Symbol>(input); + std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol> key(from, inputVariant, pop); + + std::pair<automaton::State, std::vector<alphabet::Symbol> > value = std::make_pair(to, push); + + return transitions[key].erase(value); +} + +const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol>, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >& SinglePopNPDA::getTransitions() const { + return transitions; +} + +bool SinglePopNPDA::addInitialSymbol(const alphabet::Symbol& start) { + if (stackAlphabet.find(start) == stackAlphabet.end()) { + throw AutomatonException("Stack symbol \"" + (std::string) start + "\" doesn't exist."); + } + + return this->initialSymbols.insert(start).second; +} + +bool SinglePopNPDA::removeInitialSymbol(const alphabet::Symbol& start) { + return this->initialSymbols.erase(start); +} + +void SinglePopNPDA::setInitialSymbols(const std::set<alphabet::Symbol>& symbols) { + std::set<alphabet::Symbol> tmp; + std::set_difference(symbols.begin(), symbols.end(), this->stackAlphabet.begin(), this->stackAlphabet.end(), std::inserter(tmp, tmp.end())); + if(tmp.size() != 0) + throw AutomatonException("Initial symbols not in stack alphabet"); + + this->initialSymbols = symbols; +} + +const std::set<alphabet::Symbol>& SinglePopNPDA::getInitialSymbols() const { + return initialSymbols; +} + +bool SinglePopNPDA::operator==(const AutomatonBase& other) const { + return other == *this; +} + +bool SinglePopNPDA::operator==(const SinglePopNPDA& other) const { + return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialStates == other.initialStates && this->finalStates == other.finalStates && this->stackAlphabet == other.stackAlphabet && this->initialSymbols == other.initialSymbols && this->transitions == other.transitions; +} + +void SinglePopNPDA::operator>>(std::ostream& out) const { + out << "(SinglePopNPDA" + << "states = " << states + << "inputAlphabet = " << inputAlphabet + << "initialStates = " << initialStates + << "finalStates = " << finalStates + << "stackAlphabet = " << stackAlphabet + << "initialSymbols = " << initialSymbols + << "transitions = " << transitions + << ")"; +} + +} /* namespace automaton */ diff --git a/alib2/src/automaton/PDA/SinglePopNPDA.h b/alib2/src/automaton/PDA/SinglePopNPDA.h new file mode 100644 index 0000000000000000000000000000000000000000..feee9ee94e025e2d3e664ef4813c7883ab6cfd8a --- /dev/null +++ b/alib2/src/automaton/PDA/SinglePopNPDA.h @@ -0,0 +1,134 @@ +/* + * SinglePopNPDA.h + * + * Created on: Apr 10, 2013 + * Author: martin + */ + +#ifndef SINGLE_POP_NPDA_H_ +#define SINGLE_POP_NPDA_H_ + +#include <set> +#include <map> +#include <vector> +#include "../../std/variant.hpp" +#include "../AutomatonBase.h" +#include "../common/MultiInitialStates.h" +#include "../common/InputAlphabet.h" +#include "../../alphabet/Symbol.h" +#include "../../string/Epsilon.h" + +namespace automaton { + +/** + * Push Down Automaton + */ +class SinglePopNPDA: public std::element<SinglePopNPDA, AutomatonBase>, public MultiInitialStates, public InputAlphabet { +protected: + std::set<alphabet::Symbol> stackAlphabet; + std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol>, std::set<std::pair<State, std::vector<alphabet::Symbol> > > > transitions; + std::set<alphabet::Symbol> initialSymbols; +public: + virtual AutomatonBase* clone() const; + + virtual AutomatonBase* plunder() &&; + + /** + * @copydoc Automaton::removeState(const State&) + */ + virtual bool removeState(const State& state); + + /** + * @copydoc Automaton::removeInputSymbol(const Symbol&) + */ + virtual bool removeInputSymbol(const alphabet::Symbol& symbol); + + /** + * Adds symbol to the stack alphabet. + * @param symbol Symbol to add + * @throws AutomatonException when symbol is already present in stack alphabet + */ + bool addStackSymbol(const alphabet::Symbol& symbol); + + /** + * Sets stack symbols of the automaton. + * @param symbols Symbols to set + * @throws AutomatonException when symbol is already present in stack alphabet + */ + void setStackSymbols(const std::set<alphabet::Symbol>& symbols); + + /** + * Removes symbol from the stack alphabet. + * @param symbol Symbol to remove + * @throws AutomatonException when symbol is used in transition + * (popped from or pushed to the stack), when it is a start symbol + * or when it is not present in the stack alphabet + */ + bool removeStackSymbol(const alphabet::Symbol& symbol); + + /** + * @return the stack alphabet + */ + const std::set<alphabet::Symbol>& getStackAlphabet() const; + + /** + * Adds transition to the SinglePopNPDA. + * @param transition transition to add + * @throws AutomatonException when some part of the transition is not present + * in the SinglePopNPDA (state, input symbol, stack symbol) or when transition already exists + */ + bool addTransition(const State& from, const alphabet::Symbol& input, const alphabet::Symbol& pop, const State& to, const std::vector<alphabet::Symbol>& push); + + /** + * Removes the transition from the SinglePopNPDA. + * @param transition transition to remove + * @throws AutomatonException when transition is not present in the SinglePopNPDA + */ + bool removeTransition(const State& from, const alphabet::Symbol& input, const alphabet::Symbol& pop, const State& to, const std::vector<alphabet::Symbol>& push); + + /** + * @return SinglePopNPDA transitions + */ + const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol>, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >& getTransitions() const; + + /** + * Adds initial symbol. Initial symbols are symbols that are pushed + * to the stack when SinglePopNPDA is created. + * @param start new initial symbol + * @throws AutomatonException when symbol is not present in the stack alphabet or it is already in the set + */ + bool addInitialSymbol(const alphabet::Symbol& start); + + + /** + * Adds initial symbol. Initial symbols are symbols that are pushed + * to the stack when SinglePopNPDA is created. + * @param start new initial symbol + * @throws AutomatonException when symbol is not present in the set of initial symbols + */ + bool removeInitialSymbol(const alphabet::Symbol& start); + + /** + * Sets initial symbols. Initial symbols are symbols that are pushed + * to the stack when SinglePopNPDA is created. + * @param symbols new initial symbols + * @throws AutomatonException when any of symbols is not present in the stack alphabet + */ + void setInitialSymbols(const std::set<alphabet::Symbol>& symbols); + + /** + * @return list of start symbols + */ + const std::set<alphabet::Symbol>& getInitialSymbols() const; + + virtual bool operator==(const AutomatonBase& other) const; + + virtual bool operator==(const SinglePopNPDA& other) const; + + virtual void operator>>(std::ostream& os) const; + +}; + +} /* namespace automaton */ + +#endif /* SINGLE_POP_NPDA_H_ */ diff --git a/alib2/src/factory/AutomatonConvertor.cpp b/alib2/src/factory/AutomatonConvertor.cpp index a59ac88fb00889c613b9817d14ba47d7c19387fd..2d1938cd87d78dfbf74aca1938c4b5c34b0a282a 100644 --- a/alib2/src/factory/AutomatonConvertor.cpp +++ b/alib2/src/factory/AutomatonConvertor.cpp @@ -17,8 +17,8 @@ namespace automaton { Automaton AutomatonConvertor::buildAutomaton(const UnknownAutomaton& automaton) { if (isEpsilonNFA(automaton)) { return Automaton(buildEpsilonNFA(automaton)); - } else if (isPDA(automaton)) { - return Automaton(buildPDA(automaton)); + } else if (isNPDA(automaton)) { + return Automaton(buildNPDA(automaton)); } else if (isOneTapeDTM(automaton)) { return Automaton(buildOneTapeDTM(automaton)); } else { @@ -67,7 +67,7 @@ EpsilonNFA AutomatonConvertor::buildEpsilonNFA(const UnknownAutomaton& automaton return fsm; } -bool AutomatonConvertor::isPDA(const UnknownAutomaton& automaton) { +bool AutomatonConvertor::isNPDA(const UnknownAutomaton& automaton) { if (automaton.getTapeSymbols().size() > 0 || automaton.hasBlankSymbol()) { return false; } @@ -75,7 +75,7 @@ bool AutomatonConvertor::isPDA(const UnknownAutomaton& automaton) { const std::set<UnknownTransition> transitions = automaton.getTransitions(); std::set<UnknownTransition>::const_iterator transition = transitions.begin(); while (transition != transitions.end()) { - if (!isPDATransition(*transition)) { + if (!isNPDATransition(*transition)) { return false; } transition++; @@ -84,12 +84,12 @@ bool AutomatonConvertor::isPDA(const UnknownAutomaton& automaton) { return true; } -bool AutomatonConvertor::isPDATransition(const UnknownTransition& transition) { +bool AutomatonConvertor::isNPDATransition(const UnknownTransition& transition) { return !(transition.hasOutput() || transition.getShift() != NOT_SET); } -PDA AutomatonConvertor::buildPDA(const UnknownAutomaton& automaton) { - PDA pda; +NPDA AutomatonConvertor::buildNPDA(const UnknownAutomaton& automaton) { + NPDA pda; pda.setStates(automaton.getStates()); pda.setInputSymbols(automaton.getInputSymbols()); pda.setInitialStates(automaton.getInitialStates()); diff --git a/alib2/src/factory/AutomatonConvertor.h b/alib2/src/factory/AutomatonConvertor.h index 04eaf17ab909ea43a75885d34c8cfe8d5845396b..468cc2c777469f37ec8d36845154550cf611a333 100644 --- a/alib2/src/factory/AutomatonConvertor.h +++ b/alib2/src/factory/AutomatonConvertor.h @@ -11,7 +11,7 @@ #include "../automaton/Automaton.h" #include "../automaton/UnknownAutomaton.h" #include "../automaton/FSM/EpsilonNFA.h" -#include "../automaton/PDA/PDA.h" +#include "../automaton/PDA/NPDA.h" #include "../automaton/TM/OneTapeDTM.h" namespace automaton { @@ -52,7 +52,7 @@ public: * @param automaton source UnknownAutomaton * @return true when PDA can be build from UnknownAutomaton, false otherwise */ - static bool isPDA(const UnknownAutomaton& automaton); + static bool isNPDA(const UnknownAutomaton& automaton); /** * Tries to build PDA from the UnknownAutomaton. Ignores elements that @@ -60,7 +60,7 @@ public: * @param automaton source UnknownAutomaton * @return PDA */ - static PDA buildPDA(const UnknownAutomaton& automaton); + static NPDA buildNPDA(const UnknownAutomaton& automaton); /** * Checks that TM can be build from UnknownAutomaton. That means UnknownAutomaton @@ -99,7 +99,7 @@ protected: * @param transition UnknownTransition to check * @return true when transition is PDA transition */ - static bool isPDATransition(const UnknownTransition& transition); + static bool isNPDATransition(const UnknownTransition& transition); /** * Checks that transition contains only elements that are valid for TM.