diff --git a/alib2/src/automaton/Automaton.cpp b/alib2/src/automaton/Automaton.cpp index 261db09e195971609b04f7e6aa4db45b2a38a8ec..a7e43ba65851063449de8920eab9d8aa39fbd1f2 100644 --- a/alib2/src/automaton/Automaton.cpp +++ b/alib2/src/automaton/Automaton.cpp @@ -2,12 +2,13 @@ * Automaton.cpp * * Created on: Apr 16, 2013 - * Author: martin + * Author: Martin Zak */ #include "Automaton.h" #include <set> +#include <algorithm> #include "AutomatonException.h" namespace automaton { @@ -16,55 +17,56 @@ Automaton::~Automaton() { } -void Automaton::addState(const State& state) { - std::pair<std::set<State>::iterator, bool> ret = states.insert(state); - if (!ret.second) - throw AutomatonException("State \"" + state.getName() + "\" already exists."); +bool Automaton::addState(const State& state) { + return states.insert(state).second; } -const std::set<State>& Automaton::getStates() const { - return states; -} +void Automaton::setStates(const std::set<State>& newStates) { + std::set<State> removed; + std::set_symmetric_difference(states.begin(), states.end(), newStates.begin(), newStates.end(), std::inserter(removed, removed.end())); -const std::set<alphabet::Symbol>& Automaton::getInputAlphabet() const { - return inputAlphabet; + std::set<State> added; + std::set_symmetric_difference(newStates.begin(), newStates.end(), states.begin(), states.end(), std::inserter(added, added.end())); + + for(const State& removedState : removed) { + removeState(removedState); + } + + for(const State& addedState : added) { + addState(addedState); + } } -void Automaton::addInitialState(const State& state) { - std::pair<std::set<State>::iterator, bool> ret = initialStates.insert(state); - if (!ret.second) - throw AutomatonException("State \"" + state.getName() + "\" is already initial state."); +const std::set<State>& Automaton::getStates() const { + return states; } -void Automaton::removeInitialState(const State& state) { +bool Automaton::addFinalState(const State& state) { if (states.find(state) == states.end()) { - throw AutomatonException("State cannot be set as initial state. It is not present in the automaton."); + throw AutomatonException("State cannot be set as final state. It is not present in the automaton."); } - int removed = initialStates.erase(state); - if (!removed) - throw AutomatonException("State \"" + state.getName() + "\" isn't initial state."); - + return finalStates.insert(state).second; } -const std::set<State>& Automaton::getInitialStates() const { - return initialStates; -} +void Automaton::setFinalStates(const std::set<State>& newFinalStates) { + std::set<State> removed; + std::set_symmetric_difference(finalStates.begin(), finalStates.end(), newFinalStates.begin(), newFinalStates.end(), std::inserter(removed, removed.end())); -void Automaton::addFinalState(const State& state) { - if (states.find(state) == states.end()) { - throw AutomatonException("State cannot be set as final state. It is not present in the automaton."); + std::set<State> added; + std::set_symmetric_difference(newFinalStates.begin(), newFinalStates.end(), finalStates.begin(), finalStates.end(), std::inserter(added, added.end())); + + for(const State& removedState : removed) { + removeFinalState(removedState); } - std::pair<std::set<State>::iterator, bool> ret = finalStates.insert(state); - if (!ret.second) - throw AutomatonException("State \"" + state.getName() + "\" is already final state."); + for(const State& addedState : added) { + addFinalState(addedState); + } } -void Automaton::removeFinalState(const State& state) { - int removed = finalStates.erase(state); - if (!removed) - throw AutomatonException("State \"" + state.getName() + "\" isn't final state."); +bool Automaton::removeFinalState(const State& state) { + return finalStates.erase(state); } const std::set<State>& Automaton::getFinalStates() const { diff --git a/alib2/src/automaton/Automaton.h b/alib2/src/automaton/Automaton.h index eb0a3685d6601204438fe73a4732d0673fc408ac..f5c6605ccd529ac0132c0d60b1438b42f879ab2b 100644 --- a/alib2/src/automaton/Automaton.h +++ b/alib2/src/automaton/Automaton.h @@ -2,7 +2,7 @@ * Automaton.h * * Created on: Apr 10, 2013 - * Author: martin + * Author: Martin Zak */ #ifndef AUTOMATON_H_ @@ -19,13 +19,11 @@ namespace automaton { /** - * Abstract base class for all automatons. Contains common elements of automatons. + * Abstract base class for all automata. */ class Automaton { protected: std::set<State> states; - std::set<alphabet::Symbol> inputAlphabet; - std::set<State> initialStates; std::set<State> finalStates; public: virtual ~Automaton() noexcept; @@ -35,7 +33,14 @@ public: * @param state State to add * @throws AutomatonException when state already exist in the automaton */ - void addState(const State& state); + bool addState(const State& state); + + /** + * Sets new states of the automaton. + * @param states States to set + * @throws AutomatonException when state already exist in the automaton + */ + void setStates(const std::set<State>& states); /** * Removes the state from the automaton. @@ -43,69 +48,35 @@ public: * @throws AutomatonException when state is not part of the automaton, * is set as initial or final or when it's used in a transition */ - virtual void removeState(const State& state) = 0; + virtual bool removeState(const State& state) = 0; /** * @return list of states */ const std::set<State>& getStates() const; - - /** - * Adds input symbol to input alphabet. - * @param symbol Symbol to add - * @throws AutomatonException when symbol already exists - */ - virtual void addInputSymbol(const alphabet::Symbol& symbol) = 0; - - /** - * Removes input symbol from the input alphabet. - * @param symbol Symbol to remove - * @throws AutomatonException when symbol is not present in input alphabet - * or when symbol is part of the transition - */ - virtual void removeInputSymbol(const alphabet::Symbol& symbol) = 0; - - /** - * @return the input alphabet - */ - const std::set<alphabet::Symbol>& getInputAlphabet() const; - - /** - * Adds the State to the initial states. + * Adds the State to the final states. * @param state State to add * @throws AutomatonException when state is not present - * in the automaton or when it's already initial state - */ - void addInitialState(const State& state); - - /** - * Removes the state from the initial states. - * @param state State to remove - * @throws AutomatonException when State is not initial state - */ - virtual void removeInitialState(const State& state); - - /** - * @return initial states + * in the automaton or when it's already final state */ - const std::set<State>& getInitialStates() const; + bool addFinalState(const State& state); /** - * Adds the State to the final states. - * @param state State to add + * sets the final states of the automaton. + * @param states States to set * @throws AutomatonException when state is not present * in the automaton or when it's already final state */ - void addFinalState(const State& state); + void setFinalStates(const std::set<State>& state); /** * Removes the state from the final states. * @param state State to remove * @throws AutomatonException when State is not final state */ - virtual void removeFinalState(const State& state); + virtual bool removeFinalState(const State& state); /** * @return final states diff --git a/alib2/src/automaton/AutomatonToXMLComposer.cpp b/alib2/src/automaton/AutomatonToXMLComposer.cpp index c5fd4d68b19313df5eee06612dc3dad4592aa017..3d03363033a2167c4a16b9b8932f419087f7dfe2 100644 --- a/alib2/src/automaton/AutomatonToXMLComposer.cpp +++ b/alib2/src/automaton/AutomatonToXMLComposer.cpp @@ -116,14 +116,14 @@ std::list<sax::Token> AutomatonToXMLComposer::compose(const UnknownAutomaton& au printStates(out, automaton.getStates(), "states"); } - if (automaton.getInputAlphabet().size() > 0) { - printSymbols(out, automaton.getInputAlphabet(), "inputAlphabet"); + if (automaton.getInputSymbols().size() > 0) { + printSymbols(out, automaton.getInputSymbols(), "inputAlphabet"); } - if (automaton.getTapeAlphabet().size() > 0) { - printSymbols(out, automaton.getTapeAlphabet(), "tapeAlphabet"); + if (automaton.getTapeSymbols().size() > 0) { + printSymbols(out, automaton.getTapeSymbols(), "tapeAlphabet"); } - if (automaton.getStackAlphabet().size() > 0) { - printSymbols(out, automaton.getStackAlphabet(), "stackAlphabet"); + if (automaton.getStackSymbols().size() > 0) { + printSymbols(out, automaton.getStackSymbols(), "stackAlphabet"); } if (automaton.getTransitions().size() > 0) { diff --git a/alib2/src/automaton/BlankSymbolInputTapeAlphabet.cpp b/alib2/src/automaton/BlankSymbolInputTapeAlphabet.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4bdc6e49b120e7431b86e46ab1449351a05f140 --- /dev/null +++ b/alib2/src/automaton/BlankSymbolInputTapeAlphabet.cpp @@ -0,0 +1,91 @@ +/* + * BlankSymbolInputTapeAlphabet.cpp + * + * Created on: Apr 16, 2013 + * Author: Jan Travnicek + */ + +#include "BlankSymbolInputTapeAlphabet.h" + +#include <algorithm> +#include "AutomatonException.h" + +namespace automaton { + +BlankSymbolInputTapeAlphabet::BlankSymbolInputTapeAlphabet(const alphabet::Symbol& blank) : blankSymbol(blank) { + tapeAlphabet.insert(blank); +} + +const std::set<alphabet::Symbol>& BlankSymbolInputTapeAlphabet::getInputAlphabet() const { + return inputAlphabet; +} + +bool BlankSymbolInputTapeAlphabet::addInputSymbol(const alphabet::Symbol& symbol) { + if (tapeAlphabet.find(symbol) == tapeAlphabet.end()) { + throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" is not in tape alphabet."); + } + + if (symbol == blankSymbol) { + throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" cannot be blank symbol."); + } + + return inputAlphabet.insert(symbol).second; +} + +void BlankSymbolInputTapeAlphabet::setInputSymbols(const std::set<alphabet::Symbol>& newSymbols) { + std::set<alphabet::Symbol> removed; + std::set_symmetric_difference(inputAlphabet.begin(), inputAlphabet.end(), newSymbols.begin(), newSymbols.end(), std::inserter(removed, removed.end())); + + std::set<alphabet::Symbol> added; + std::set_symmetric_difference(newSymbols.begin(), newSymbols.end(), inputAlphabet.begin(), inputAlphabet.end(), std::inserter(added, added.end())); + + for(const alphabet::Symbol& removedSymbol : removed) { + removeInputSymbol(removedSymbol); + } + + for(const alphabet::Symbol& addedSymbol : added) { + addInputSymbol(addedSymbol); + } +} + +bool BlankSymbolInputTapeAlphabet::addTapeSymbol(const alphabet::Symbol& symbol) { + return tapeAlphabet.insert(symbol).second; +} + +void BlankSymbolInputTapeAlphabet::setTapeSymbols(const std::set<alphabet::Symbol>& newSymbols) { + std::set<alphabet::Symbol> removed; + std::set_symmetric_difference(tapeAlphabet.begin(), tapeAlphabet.end(), newSymbols.begin(), newSymbols.end(), std::inserter(removed, removed.end())); + + std::set<alphabet::Symbol> added; + std::set_symmetric_difference(newSymbols.begin(), newSymbols.end(), tapeAlphabet.begin(), tapeAlphabet.end(), std::inserter(added, added.end())); + + for(const alphabet::Symbol& removedSymbol : removed) { + removeTapeSymbol(removedSymbol); + } + + for(const alphabet::Symbol& addedSymbol : added) { + addTapeSymbol(addedSymbol); + } +} + +const std::set<alphabet::Symbol>& BlankSymbolInputTapeAlphabet::getTapeAlphabet() const { + return tapeAlphabet; +} + +void BlankSymbolInputTapeAlphabet::setBlankSymbol(const alphabet::Symbol& symbol) { + if (inputAlphabet.find(symbol) != inputAlphabet.end()) + throw AutomatonException("Blank symbol \"" + symbol.getSymbol() + "\" is in input alphabet."); + + if (tapeAlphabet.find(symbol) == tapeAlphabet.end()) + throw AutomatonException("Blank symbol \"" + symbol.getSymbol() + "\" is not in tape alphabet."); + + blankSymbol = symbol; + +} + +const alphabet::Symbol& BlankSymbolInputTapeAlphabet::getBlankSymbol() const { + return blankSymbol; +} + +} /* namespace automaton */ + diff --git a/alib2/src/automaton/BlankSymbolInputTapeAlphabet.h b/alib2/src/automaton/BlankSymbolInputTapeAlphabet.h new file mode 100644 index 0000000000000000000000000000000000000000..d94082f8fb5ac72bce6db860422bc734db6af575 --- /dev/null +++ b/alib2/src/automaton/BlankSymbolInputTapeAlphabet.h @@ -0,0 +1,94 @@ +/* + * BlankSymbolInputTapeAlphabet.h + * + * Created on: Apr 10, 2013 + * Author: Jan Travnicek + */ + +#ifndef BLANK_SYMBOL_INPUT_TAPE_ALPHABET_H_ +#define BLANK_SYMBOL_INPUT_TAPE_ALPHABET_H_ + +#include <set> +#include "../alphabet/Symbol.h" + +namespace automaton { + +class BlankSymbolInputTapeAlphabet { +protected: + std::set<alphabet::Symbol> tapeAlphabet; + std::set<alphabet::Symbol> inputAlphabet; + alphabet::Symbol blankSymbol; +public: + BlankSymbolInputTapeAlphabet(const alphabet::Symbol& blank); + + /** + * Adds input symbol to input alphabet. + * @param symbol Symbol to add + * @throws AutomatonException when symbol already exists + */ + bool addInputSymbol(const alphabet::Symbol& symbol); + + /** + * Sets input symbols of the automaton. + * @param symbols Symbols to set + * @throws AutomatonException when symbol already exists + */ + void setInputSymbols(const std::set<alphabet::Symbol>& symbol); + + /** + * Removes input symbol from the input alphabet. + * @param symbol Symbol to remove + * @throws AutomatonException when symbol is not present in input alphabet + * or when symbol is part of the transition + */ + virtual bool removeInputSymbol(const alphabet::Symbol& symbol) = 0; + + /** + * @return the input alphabet + */ + const std::set<alphabet::Symbol>& getInputAlphabet() const; + + /** + * Adds symbol to the tape alphabet. + * @param symbol Symbol to add + * @throw AutomatonException when Symbol is already present in tape alphabet + */ + bool addTapeSymbol(const alphabet::Symbol& symbol); + + /** + * Sets tape symbols of the automaton. + * @param symbols Symbols to set + * @throw AutomatonException when Symbol is already present in tape alphabet + */ + void setTapeSymbols(const std::set<alphabet::Symbol>& symbols); + + /** + * Removes symbol from the tape alphabet. + * @param symbol Symbol to remove + * @throw AutomatonException when Symbol is not present in the tape alphabet, + * when it is used in transition or when it is present in input alphabet + */ + virtual bool removeTapeSymbol(const alphabet::Symbol& symbol) = 0; + + /** + * @return tape alphabet + */ + const std::set<alphabet::Symbol>& getTapeAlphabet() const; + + /** + * Sets the blank symbol = symbol representing empty cell of the tape + * @param symbol Symbol to set + */ + void setBlankSymbol(const alphabet::Symbol& symbol); + + /** + * @return symbol representing empty cell of the tape + */ + const alphabet::Symbol& getBlankSymbol() const; + +}; + +} /* namespace automaton */ + +#endif /* BLANK_SYMBOL_INPUT_TAPE_ALPHABET_H_ */ + diff --git a/alib2/src/automaton/DeterministicAutomaton.cpp b/alib2/src/automaton/DeterministicAutomaton.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2cd693a2199d8fdb6f39ac357f860be071300eae --- /dev/null +++ b/alib2/src/automaton/DeterministicAutomaton.cpp @@ -0,0 +1,31 @@ +/* + * DeterministicAutomaton.cpp + * + * Created on: Apr 16, 2013 + * Author: Jan Travnicek + */ + +#include "DeterministicAutomaton.h" + +#include "AutomatonException.h" + +namespace automaton { + +DeterministicAutomaton::DeterministicAutomaton(const State& initialState) : initialState(initialState) { + addState(initialState); +} + +void DeterministicAutomaton::setInitialState(const State& state) { + if (states.find(state) == states.end()) { + throw AutomatonException("State cannot be set as initial state. It is not present in the automaton."); + } + + initialState = state; +} + +const State& DeterministicAutomaton::getInitialState() const { + return initialState; +} + +} /* namespace automaton */ + diff --git a/alib2/src/automaton/DeterministicAutomaton.h b/alib2/src/automaton/DeterministicAutomaton.h new file mode 100644 index 0000000000000000000000000000000000000000..6eebaa481c961fb94df8ac1f3c1dff53732b0d6a --- /dev/null +++ b/alib2/src/automaton/DeterministicAutomaton.h @@ -0,0 +1,42 @@ +/* + * DeterministicAutomaton.h + * + * Created on: Apr 10, 2013 + * Author: Jan Travnicek + */ + +#ifndef DETERMINISTIC_AUTOMATON_H_ +#define DETERMINISTIC_AUTOMATON_H_ + +#include "Automaton.h" +#include "State.h" + +namespace automaton { + +/** + * Base class for deterministic automata. Contains common elements of automata. + */ +class DeterministicAutomaton : public Automaton { +protected: + State initialState; +public: + DeterministicAutomaton(const State& initialState); + + /** + * Set the initial state. + * @param state State to set + * @throws AutomatonException when state is not present + * in the automaton + */ + void setInitialState(const State& state); + + /** + * @return initial state + */ + const State& getInitialState() const; +}; + +} /* namespace automaton */ + +#endif /* DETERMINISTIC_AUTOMATON_H_ */ + diff --git a/alib2/src/automaton/FSM/CompactFA.cpp b/alib2/src/automaton/FSM/CompactFA.cpp deleted file mode 100644 index 639d63b7c565ed70ec2d63df25e4916a228d3f9a..0000000000000000000000000000000000000000 --- a/alib2/src/automaton/FSM/CompactFA.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * CompactFA.cpp - * - * Created on: Mar 25, 2013 - * Author: Jan Travnicek - */ - -#include "CompactFA.h" -#include "../AutomatonException.h" -#include <ostream> -#include <algorithm> - -namespace automaton { - -void CompactFA::addInputSymbol(const alphabet::Symbol& symbol) { - std::pair<std::set<alphabet::Symbol>::iterator, bool> ret = inputAlphabet.insert(symbol); - if (!ret.second) - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" already exists."); -} - -void CompactFA::removeState(const State& state) { - if (initialStates.find(state) != initialStates.end()) { - throw AutomatonException("State \"" + state.getName() + "\" is initial state."); - } - - if (finalStates.find(state) != finalStates.end()) { - throw AutomatonException("State \"" + state.getName() + "\" is final state."); - } - - for (std::map<std::pair<State, string::String>, State>::const_iterator t = transitions.begin(); t != transitions.end(); t++) { - if (t->first.first == state || t->second == state) - throw AutomatonException("State \"" + state.getName() + "\" is used in transition."); - } - - int removed = states.erase(state); - if (!removed) - throw AutomatonException("State \"" + state.getName() + "\" doesn't exist."); -} - -void CompactFA::removeInputSymbol(const alphabet::Symbol& symbol) { - for (std::map<std::pair<State, string::String>, State>::const_iterator transition = transitions.begin(); transition != transitions.end(); - transition++) { - if (transition->first.second.getAlphabet().count(symbol) == 1) - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" is used."); - } - - int removed = inputAlphabet.erase(symbol); - if (!removed) - throw AutomatonException("Input symbol \"set of symbols\" doesn't exist."); //TODO - -} - -void CompactFA::addTransition(const State& from, const string::String& input, const State& to) { - if (states.find(from) == states.end()) - throw AutomatonException("State \"" + from.getName() + "\" doesn't exist."); - - std::set<alphabet::Symbol> inputStringAlphabet; - std::set_symmetric_difference(inputAlphabet.begin(), inputAlphabet.end(), input.getAlphabet().begin(), input.getAlphabet().end(), std::inserter(inputStringAlphabet, inputStringAlphabet.end())); - if (inputStringAlphabet.size() != 0) - throw AutomatonException("Input string is over different alphabet than automaton"); - - if (states.find(to) == states.end()) - throw AutomatonException("State \"" + to.getName() + "\" doesn't exist."); - - std::pair<State, string::String> key = make_pair(from, input); - - if (transitions.find(key) != transitions.end()) - throw AutomatonException( - "Transition (\"" + from.getName() + "\", \"" + "array of symbols" + "\") -> \"" + to.getName() - + "\" already exists."); //TODO - - transitions.insert(make_pair(key, to)); -} - -void CompactFA::removeTransition(const State& from, const string::String& input, const State& to) { - std::pair<State, string::String> key = make_pair(from, input); - - if (transitions.find(key) == transitions.end()) - throw AutomatonException( - "Transition (\"" + from.getName() + "\", \"" + "array of symbol" - + "\") -> \"" + to.getName() + "\" doesn't exist."); - - transitions.erase(key); -} - -const std::map<std::pair<State, string::String>, State>& CompactFA::getTransitions() const { - return transitions; -} - -std::map<std::pair<State, string::String>, State> CompactFA::getTransitionsFromState(const State& from) const { - if( states.find(from) == states.end()) - throw AutomatonException("State \"" + from.getName() + "\" doesn't exist"); - - std::map<std::pair<State, string::String>, State> transitionsFromState; - for (std::map<std::pair<State, string::String>, State>::const_iterator transition = transitions.begin(); transition != transitions.end(); - transition++) { - if (transition->first.first == from) { - transitionsFromState.insert(make_pair(transition->first, transition->second)); - } - } - - return transitionsFromState; -} - -std::map<std::pair<State, string::String>, State> CompactFA::getTransitionsToState(const State& to) const { - if( states.find(to) == states.end()) - throw AutomatonException("State \"" + to.getName() + "\" doesn't exist"); - - std::map<std::pair<State, string::String>, State> transitionsToState; - for (std::map<std::pair<State, string::String>, State>::const_iterator transition = transitions.begin(); transition != transitions.end(); - transition++) { - if (transition->second == to) { - transitionsToState.insert(make_pair(transition->first, transition->second)); - } - } - - return transitionsToState; -} - -} /* namespace automaton */ diff --git a/alib2/src/automaton/FSM/CompactNFA.cpp b/alib2/src/automaton/FSM/CompactNFA.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0e2b2ed2d95dab60312ccf656daa62d371cfd138 --- /dev/null +++ b/alib2/src/automaton/FSM/CompactNFA.cpp @@ -0,0 +1,99 @@ +/* + * CompactNFA.cpp + * + * Created on: Mar 25, 2013 + * Author: Jan Travnicek + */ + +#include "CompactNFA.h" +#include "../AutomatonException.h" +#include <ostream> +#include <algorithm> + +namespace automaton { + +bool CompactNFA::removeState(const State& state) { + if (initialStates.find(state) != initialStates.end()) { + throw AutomatonException("State \"" + state.getName() + "\" is initial state."); + } + + if (finalStates.find(state) != finalStates.end()) { + throw AutomatonException("State \"" + state.getName() + "\" is final state."); + } + + for (std::map<std::pair<State, string::String>, std::set<State> >::const_iterator t = transitions.begin(); t != transitions.end(); t++) { + if (t->first.first == state || t->second.find(state) != t->second.end()) + throw AutomatonException("State \"" + state.getName() + "\" is used in transition."); + } + + return states.erase(state); +} + +bool CompactNFA::removeInputSymbol(const alphabet::Symbol& symbol) { + for (std::map<std::pair<State, string::String>, std::set<State> >::const_iterator transition = transitions.begin(); transition != transitions.end(); + transition++) { + if (transition->first.second.getAlphabet().count(symbol) == 1) + throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" is used."); + } + + return inputAlphabet.erase(symbol); +} + +bool CompactNFA::addTransition(const State& from, const string::String& input, const State& to) { + if (states.find(from) == states.end()) + throw AutomatonException("State \"" + from.getName() + "\" doesn't exist."); + + std::set<alphabet::Symbol> inputStringAlphabet; + std::set_symmetric_difference(inputAlphabet.begin(), inputAlphabet.end(), input.getAlphabet().begin(), input.getAlphabet().end(), std::inserter(inputStringAlphabet, inputStringAlphabet.end())); + if (inputStringAlphabet.size() != 0) + throw AutomatonException("Input string is over different alphabet than automaton"); + + if (states.find(to) == states.end()) + throw AutomatonException("State \"" + to.getName() + "\" doesn't exist."); + + std::pair<State, string::String> key = make_pair(from, input); + + return transitions[key].insert(to).second; +} + +bool CompactNFA::removeTransition(const State& from, const string::String& input, const State& to) { + std::pair<State, string::String> key = make_pair(from, input); + + return transitions[key].erase(to); +} + +const std::map<std::pair<State, string::String>, std::set<State>>& CompactNFA::getTransitions() const { + return transitions; +} + +std::map<std::pair<State, string::String>, std::set<State>> CompactNFA::getTransitionsFromState(const State& from) const { + if( states.find(from) == states.end()) + throw AutomatonException("State \"" + from.getName() + "\" doesn't exist"); + + std::map<std::pair<State, string::String>, std::set<State>> transitionsFromState; + for (std::map<std::pair<State, string::String>, std::set<State>>::const_iterator transition = transitions.begin(); transition != transitions.end(); + transition++) { + if (transition->first.first == from) { + transitionsFromState.insert(make_pair(transition->first, transition->second)); + } + } + + return transitionsFromState; +} + +std::map<std::pair<State, string::String>, std::set<State>> CompactNFA::getTransitionsToState(const State& to) const { + if( states.find(to) == states.end()) + throw AutomatonException("State \"" + to.getName() + "\" doesn't exist"); + + std::map<std::pair<State, string::String>, std::set<State>> transitionsToState; + for (std::map<std::pair<State, string::String>, std::set<State>>::const_iterator transition = transitions.begin(); transition != transitions.end(); + transition++) { + if (transition->second.find(to) != transition->second.end()) { + transitionsToState.insert(make_pair(transition->first, transition->second)); + } + } + + return transitionsToState; +} + +} /* namespace automaton */ diff --git a/alib2/src/automaton/FSM/CompactFA.h b/alib2/src/automaton/FSM/CompactNFA.h similarity index 57% rename from alib2/src/automaton/FSM/CompactFA.h rename to alib2/src/automaton/FSM/CompactNFA.h index f186ff666dae870b55472384c3bbae18f3cf3192..8646067567c28b7f0037d3dcfb130d1ad031ac66 100644 --- a/alib2/src/automaton/FSM/CompactFA.h +++ b/alib2/src/automaton/FSM/CompactNFA.h @@ -1,15 +1,16 @@ /* - * CompactFA.h + * CompactNFA.h * * Created on: Mar 25, 2013 * Author: Jan Travnicek */ -#ifndef COMPACT_FA_H_ -#define COMPACT_FA_H_ +#ifndef COMPACT_DFA_H_ +#define COMPACT_DFA_H_ #include <map> -#include "../Automaton.h" +#include "../NondeterministicAutomaton.h" +#include "../InputAlphabet.h" #include "../State.h" #include "../../string/String.h" @@ -19,25 +20,20 @@ namespace automaton { * Represents Finite Automaton. * Can store nondeterministic finite automaton without epsilon transitions. */ -class CompactFA : public Automaton { +class CompactNFA : public NondeterministicAutomaton, public InputAlphabet { protected: - std::map<std::pair<State, string::String>, State> transitions; + std::map<std::pair<State, string::String>, std::set<State> > transitions; public: - /** - * @copydoc Automaton::addInputSymbol(const Symbol&) - */ - virtual void addInputSymbol(const alphabet::Symbol& symbol); - /** * @copydoc Automaton::removeState(const State&) */ - virtual void removeState(const State& state); + virtual bool removeState(const State& state); /** * @copydoc Automaton::removeInputSymbol(const Symbol&) */ - virtual void removeInputSymbol(const alphabet::Symbol& symbol); + virtual bool removeInputSymbol(const alphabet::Symbol& symbol); /** * Adds transition defined by parameters to the automaton. @@ -46,33 +42,33 @@ public: * @param next next state * @throws AutomatonException when transition already exists or when transition contains state or symbol not present in the automaton */ - void addTransition(const State& current, const string::String& input, const State& next); + bool addTransition(const State& current, const string::String& input, const State& next); /** * Removes transition from the automaton. * @param transition transition to remove * @throws AutomatonException when transition doesn't exists. */ - void removeTransition(const State& current, const string::String& input, const State& next); + bool removeTransition(const State& current, const string::String& input, const State& next); /** * @return automaton transitions */ - const std::map<std::pair<State, string::String>, State>& getTransitions() const; + const std::map<std::pair<State, string::String>, std::set<State>>& getTransitions() const; /** * @return automaton transitions from state */ - std::map<std::pair<State, string::String>, State> getTransitionsFromState(const State& from) const; + std::map<std::pair<State, string::String>, std::set<State>> getTransitionsFromState(const State& from) const; /** * @return automaton transitions to state */ - std::map<std::pair<State, string::String>, State> getTransitionsToState(const State& from) const; + std::map<std::pair<State, string::String>, std::set<State>> getTransitionsToState(const State& from) const; - friend std::ostream& operator<<(std::ostream& out, const CompactFA& automaton); + friend std::ostream& operator<<(std::ostream& out, const CompactNFA& automaton); }; } /* namespace automaton */ -#endif /* COMPACT_FA_H_ */ +#endif /* COMPACT_DFA_H_ */ diff --git a/alib2/src/automaton/FSM/DFA.cpp b/alib2/src/automaton/FSM/DFA.cpp index 45e75ff3755c7ac3f0d374f2672b72bc164f313d..1f9c0b1abbb8c3ad3064a1158394dcd6e9909bd4 100644 --- a/alib2/src/automaton/FSM/DFA.cpp +++ b/alib2/src/automaton/FSM/DFA.cpp @@ -11,8 +11,12 @@ namespace automaton { -void DFA::removeState(const State& state) { - if (initialStates.find(state) != initialStates.end()) { +DFA::DFA(const State& initialState) : DeterministicAutomaton(initialState) { + +} + +bool DFA::removeState(const State& state) { + if (initialState == state) { throw AutomatonException("State \"" + state.getName() + "\" is initial state."); } @@ -25,25 +29,21 @@ void DFA::removeState(const State& state) { throw AutomatonException("State \"" + state.getName() + "\" is used in transition."); } - int removed = states.erase(state); - if (!removed) - throw AutomatonException("State \"" + state.getName() + "\" doesn't exist."); + return states.erase(state); } -void DFA::removeInputSymbol(const alphabet::Symbol& symbol) { +bool DFA::removeInputSymbol(const alphabet::Symbol& symbol) { for (std::map<std::pair<State, alphabet::Symbol>, State>::const_iterator transition = transitions.begin(); transition != transitions.end(); transition++) { if (transition->first.second == symbol) throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" is used."); } - int removed = inputAlphabet.erase(symbol); - if (!removed) - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" doesn't exist."); + return inputAlphabet.erase(symbol); } -void DFA::addTransition(const State& from, const alphabet::Symbol& input, const State& to) { +bool DFA::addTransition(const State& from, const alphabet::Symbol& input, const State& to) { if (states.find(from) == states.end()) throw AutomatonException("State \"" + from.getName() + "\" doesn't exist."); @@ -55,23 +55,32 @@ void DFA::addTransition(const State& from, const alphabet::Symbol& input, const std::pair<State, alphabet::Symbol> key = std::make_pair(from, input); - if (transitions.find(key) != transitions.end()) - throw AutomatonException( + if (transitions.find(key) != transitions.end()) { + if(transitions.find(key)->second == to) + return false; + else + throw AutomatonException( "Transition (\"" + from.getName() + "\", \"" + input.getSymbol() + "\") -> \"" + to.getName() + "\" already exists."); + } transitions.insert(std::make_pair(key, to)); + return true; } -void DFA::removeTransition(const State& from, const alphabet::Symbol& input, const State& to) { +bool DFA::removeTransition(const State& from, const alphabet::Symbol& input, const State& to) { std::pair<State, alphabet::Symbol> key = std::make_pair(from, input); if (transitions.find(key) == transitions.end()) + return false; + + if(transitions.find(key)->second != to) throw AutomatonException( "Transition (\"" + from.getName() + "\", \"" + input.getSymbol() + "\") -> \"" + to.getName() + "\" doesn't exist."); transitions.erase(key); + return true; } const std::map<std::pair<State, alphabet::Symbol>, State>& DFA::getTransitions() const { @@ -108,6 +117,10 @@ std::map<std::pair<State, alphabet::Symbol>, State> DFA::getTransitionsToState(c return transitionsToState; } +bool DFA::operator==(const DFA& other) const { + return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialState == other.initialState && this->finalStates == other.finalStates && this->transitions == other.transitions; +} + bool DFA::isTotal() const { return transitions.size() == inputAlphabet.size() * states.size(); } diff --git a/alib2/src/automaton/FSM/DFA.h b/alib2/src/automaton/FSM/DFA.h index 060854fd3339f9d53fc7645a8e4e202857199a8f..c78d931f45804492064152e14ef2f6f48337387c 100644 --- a/alib2/src/automaton/FSM/DFA.h +++ b/alib2/src/automaton/FSM/DFA.h @@ -9,7 +9,8 @@ #define DFA_H_ #include <map> -#include "FSM.h" +#include "../DeterministicAutomaton.h" +#include "../InputAlphabet.h" #include "../State.h" #include "../../alphabet/Symbol.h" @@ -19,19 +20,21 @@ namespace automaton { * Represents Finite Automaton. * Can store nondeterministic finite automaton without epsilon transitions. */ -class DFA : public FSM { +class DFA : public DeterministicAutomaton, public InputAlphabet { protected: std::map<std::pair<State, alphabet::Symbol>, State> transitions; public: + DFA(const State& initialState); + /** * @copydoc Automaton::removeState(const State&) */ - virtual void removeState(const State& state); + virtual bool removeState(const State& state); /** * @copydoc Automaton::removeInputSymbol(const Symbol&) */ - virtual void removeInputSymbol(const alphabet::Symbol& symbol); + virtual bool removeInputSymbol(const alphabet::Symbol& symbol); /** * Adds transition defined by parameters to the automaton. @@ -40,14 +43,14 @@ public: * @param next next state * @throws AutomatonException when transition already exists or when transition contains state or symbol not present in the automaton */ - void addTransition(const State& current, const alphabet::Symbol& input, const State& next); + bool addTransition(const State& current, const alphabet::Symbol& input, const State& next); /** * Removes transition from the automaton. * @param transition transition to remove * @throws AutomatonException when transition doesn't exists. */ - void removeTransition(const State& current, const alphabet::Symbol& input, const State& next); + bool removeTransition(const State& current, const alphabet::Symbol& input, const State& next); /** * @return automaton transitions @@ -72,6 +75,8 @@ public: * @return true when automaton is total deterministic, false otherwise */ bool isTotal() const; + + bool operator==(const DFA& other) const; friend std::ostream& operator<<(std::ostream& out, const DFA& automaton); }; diff --git a/alib2/src/automaton/FSM/EpsilonNFA.cpp b/alib2/src/automaton/FSM/EpsilonNFA.cpp index 42abf2de12346dd287ba6d9d387e220fabfe78c8..fa208742d543d0f3a1b2d6455809a1af173a2f0f 100644 --- a/alib2/src/automaton/FSM/EpsilonNFA.cpp +++ b/alib2/src/automaton/FSM/EpsilonNFA.cpp @@ -11,7 +11,7 @@ namespace automaton { -void EpsilonNFA::removeState(const State& state) { +bool EpsilonNFA::removeState(const State& state) { if (initialStates.find(state) != initialStates.end()) { throw AutomatonException("State \"" + state.getName() + "\" is initial state."); } @@ -25,12 +25,10 @@ void EpsilonNFA::removeState(const State& state) { throw AutomatonException("State \"" + state.getName() + "\" is used in transition."); } - int removed = states.erase(state); - if (!removed) - throw AutomatonException("State \"" + state.getName() + "\" doesn't exist."); + return states.erase(state); } -void EpsilonNFA::removeInputSymbol(const alphabet::Symbol& symbol) { +bool EpsilonNFA::removeInputSymbol(const alphabet::Symbol& symbol) { std::variant<string::Epsilon, alphabet::Symbol> inputVariant; inputVariant.set<alphabet::Symbol>(symbol); for (std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol> >, std::set<State> >::const_iterator transition = transitions.begin(); transition != transitions.end(); @@ -39,13 +37,11 @@ void EpsilonNFA::removeInputSymbol(const alphabet::Symbol& symbol) { throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" is used."); } - int removed = inputAlphabet.erase(symbol); - if (!removed) - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" doesn't exist."); + return inputAlphabet.erase(symbol); } -void EpsilonNFA::addTransition(const State& from, const std::variant<string::Epsilon, alphabet::Symbol>& input, const State& to) { +bool EpsilonNFA::addTransition(const State& from, const std::variant<string::Epsilon, alphabet::Symbol>& input, const State& to) { if (states.find(from) == states.end()) throw AutomatonException("State \"" + from.getName() + "\" doesn't exist."); @@ -57,46 +53,35 @@ void EpsilonNFA::addTransition(const State& from, const std::variant<string::Eps std::pair<State, std::variant<string::Epsilon, alphabet::Symbol> > key = std::make_pair(from, input); - std::pair<std::set<automaton::State>::iterator, bool> ret = transitions[key].insert(to); - if (!ret.second) - throw AutomatonException( - "Transition (\"" + from.getName() + "\", \"" + input.get<alphabet::Symbol>().getSymbol() + "\") -> \"" + to.getName() - + "\" already exists."); + return transitions[key].insert(to).second; } -void EpsilonNFA::addTransition(const State& from, const alphabet::Symbol& input, const State& to) { +bool EpsilonNFA::addTransition(const State& from, const alphabet::Symbol& input, const State& to) { std::variant<string::Epsilon, alphabet::Symbol> inputVariant; inputVariant.set<alphabet::Symbol>(input); - addTransition(from, inputVariant, to); + return addTransition(from, inputVariant, to); } -void EpsilonNFA::addTransition(const State& from, const State& to) { +bool EpsilonNFA::addTransition(const State& from, const State& to) { std::variant<string::Epsilon, alphabet::Symbol> inputVariant; inputVariant.set<string::Epsilon>(string::Epsilon()); - addTransition(from, inputVariant, to); + return addTransition(from, inputVariant, to); } -void EpsilonNFA::removeTransition(const State& from, const alphabet::Symbol& input, const State& to) { +bool EpsilonNFA::removeTransition(const State& from, const alphabet::Symbol& input, const State& to) { std::variant<string::Epsilon, alphabet::Symbol> inputVariant; inputVariant.set<alphabet::Symbol>(input); std::pair<State, std::variant<string::Epsilon, alphabet::Symbol> > key = std::make_pair(from, inputVariant); - int removed = transitions[key].erase(to); - if (!removed) - throw AutomatonException( - "Transition (\"" + from.getName() + "\", \"" + input.getSymbol() - + "\") -> \"" + to.getName() + "\" doesn't exist."); + return transitions[key].erase(to); } -void EpsilonNFA::removeTransition(const State& from, const State& to) { +bool EpsilonNFA::removeTransition(const State& from, const State& to) { std::variant<string::Epsilon, alphabet::Symbol> inputVariant; inputVariant.set<string::Epsilon>(string::Epsilon()); std::pair<State, std::variant<string::Epsilon, alphabet::Symbol> > key = std::make_pair(from, inputVariant); - int removed = transitions[key].erase(to); - if (!removed) - throw AutomatonException( - "Transition (\"" + from.getName() + ") -> \"" + to.getName() + "\" doesn't exist."); + return transitions[key].erase(to); } const std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol> >, std::set<State> >& EpsilonNFA::getTransitions() const { diff --git a/alib2/src/automaton/FSM/EpsilonNFA.h b/alib2/src/automaton/FSM/EpsilonNFA.h index ed6202923b08474db60af6efb96d572a543f06ef..01f667d17787781dec50448cb98465ec966282a3 100644 --- a/alib2/src/automaton/FSM/EpsilonNFA.h +++ b/alib2/src/automaton/FSM/EpsilonNFA.h @@ -10,7 +10,8 @@ #include <map> #include "../../std/variant.hpp" -#include "FSM.h" +#include "../NondeterministicAutomaton.h" +#include "../InputAlphabet.h" #include "../State.h" #include "../../alphabet/Symbol.h" #include "../../string/Epsilon.h" @@ -21,19 +22,19 @@ namespace automaton { * Represents Finite Automaton. * Can store nondeterministic finite automaton with epsilon transitions. */ -class EpsilonNFA : public FSM { +class EpsilonNFA : public NondeterministicAutomaton, public InputAlphabet { protected: std::map<std::pair<State, std::variant<string::Epsilon, alphabet::Symbol> >, std::set<State> > transitions; public: /** * @copydoc Automaton::removeState(const State&) */ - virtual void removeState(const State& state); + virtual bool removeState(const State& state); /** * @copydoc Automaton::removeInputSymbol(const Symbol&) */ - virtual void removeInputSymbol(const alphabet::Symbol& symbol); + virtual bool removeInputSymbol(const alphabet::Symbol& symbol); /** * Adds transition defined by parameters to the automaton. @@ -42,7 +43,7 @@ public: * @param next next state * @throws AutomatonException when transition already exists or when transition contains state or symbol not present in the automaton */ - void addTransition(const State& from, const std::variant<string::Epsilon, alphabet::Symbol>& input, const State& to); + bool addTransition(const State& from, const std::variant<string::Epsilon, alphabet::Symbol>& input, const State& to); /** * Adds transition defined by parameters to the automaton. @@ -51,7 +52,7 @@ public: * @param next next state * @throws AutomatonException when transition already exists or when transition contains state or symbol not present in the automaton */ - void addTransition(const State& from, const alphabet::Symbol& input, const State& to); + bool addTransition(const State& from, const alphabet::Symbol& input, const State& to); /** * Adds transition defined by parameters to the automaton. @@ -59,21 +60,21 @@ public: * @param next next state * @throws AutomatonException when transition already exists or when transition contains state or symbol not present in the automaton */ - void addTransition(const State& from, const State& to); + bool addTransition(const State& from, const State& to); /** * Removes transition from the automaton. * @param transition transition to remove * @throws AutomatonException when transition doesn't exists. */ - void removeTransition(const State& current, const alphabet::Symbol& input, const State& next); + bool removeTransition(const State& current, const alphabet::Symbol& input, const State& next); /** * Removes transition from the automaton. * @param transition transition to remove * @throws AutomatonException when transition doesn't exists. */ - void removeTransition(const State& current, const State& next); + bool removeTransition(const State& current, const State& next); /** * @return automaton transitions diff --git a/alib2/src/automaton/FSM/ExtendedFA.cpp b/alib2/src/automaton/FSM/ExtendedFA.cpp deleted file mode 100644 index 6923fab46c494780691c0c379a5b789423abb1a7..0000000000000000000000000000000000000000 --- a/alib2/src/automaton/FSM/ExtendedFA.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * ExtendedFA.cpp - * - * Created on: Mar 25, 2013 - * Author: Jan Travnicek - */ - -#include "ExtendedFA.h" -#include "../AutomatonException.h" -#include <ostream> -#include <algorithm> - -namespace automaton { - -void ExtendedFA::addInputSymbol(const alphabet::Symbol& symbol) { - std::pair<std::set<alphabet::Symbol>::iterator, bool> ret = inputAlphabet.insert(symbol); - if (!ret.second) - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" already exists."); -} - -void ExtendedFA::removeState(const State& state) { - if (initialStates.find(state) != initialStates.end()) { - throw AutomatonException("State \"" + state.getName() + "\" is initial state."); - } - - if (finalStates.find(state) != finalStates.end()) { - throw AutomatonException("State \"" + state.getName() + "\" is final state."); - } - - for (std::map<std::pair<State, regexp::RegExp>, State>::const_iterator t = transitions.begin(); t != transitions.end(); t++) { - if (t->first.first == state || t->second == state) - throw AutomatonException("State \"" + state.getName() + "\" is used in transition."); - } - - int removed = states.erase(state); - if (!removed) - throw AutomatonException("State \"" + state.getName() + "\" doesn't exist."); -} - -void ExtendedFA::removeInputSymbol(const alphabet::Symbol& symbol) { - for (std::map<std::pair<State, regexp::RegExp>, State>::const_iterator transition = transitions.begin(); transition != transitions.end(); - transition++) { - if (transition->first.second.getAlphabet().count(symbol) == 1) - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" is used."); - } - - int removed = inputAlphabet.erase(symbol); - if (!removed) - throw AutomatonException("Input symbol \"set of symbols\" doesn't exist."); //TODO - -} - -void ExtendedFA::addTransition(const State& from, const regexp::RegExp& input, const State& to) { - if (states.find(from) == states.end()) - throw AutomatonException("State \"" + from.getName() + "\" doesn't exist."); - - std::set<alphabet::Symbol> inputRegExpAlphabet; - std::set_symmetric_difference(inputAlphabet.begin(), inputAlphabet.end(), input.getAlphabet().begin(), input.getAlphabet().end(), std::inserter(inputRegExpAlphabet, inputRegExpAlphabet.end())); - if (inputRegExpAlphabet.size() != 0) - throw AutomatonException("Input string is over different alphabet than automaton"); - - if (states.find(to) == states.end()) - throw AutomatonException("State \"" + to.getName() + "\" doesn't exist."); - - std::pair<State, regexp::RegExp> key = make_pair(from, input); - - if (transitions.find(key) != transitions.end()) - throw AutomatonException( - "Transition (\"" + from.getName() + "\", \"" + "array of symbols" + "\") -> \"" + to.getName() - + "\" already exists."); //TODO - - transitions.insert(make_pair(key, to)); -} - -void ExtendedFA::removeTransition(const State& from, const regexp::RegExp& input, const State& to) { - std::pair<State, regexp::RegExp> key = make_pair(from, input); - - if (transitions.find(key) == transitions.end()) - throw AutomatonException( - "Transition (\"" + from.getName() + "\", \"" + "array of symbol" - + "\") -> \"" + to.getName() + "\" doesn't exist."); - - transitions.erase(key); -} - -const std::map<std::pair<State, regexp::RegExp>, State>& ExtendedFA::getTransitions() const { - return transitions; -} - -std::map<std::pair<State, regexp::RegExp>, State> ExtendedFA::getTransitionsFromState(const State& from) const { - if( states.find(from) == states.end()) - throw AutomatonException("State \"" + from.getName() + "\" doesn't exist"); - - std::map<std::pair<State, regexp::RegExp>, State> transitionsFromState; - for (std::map<std::pair<State, regexp::RegExp>, State>::const_iterator transition = transitions.begin(); transition != transitions.end(); - transition++) { - if (transition->first.first == from) { - transitionsFromState.insert(make_pair(transition->first, transition->second)); - } - } - - return transitionsFromState; -} - -std::map<std::pair<State, regexp::RegExp>, State> ExtendedFA::getTransitionsToState(const State& to) const { - if( states.find(to) == states.end()) - throw AutomatonException("State \"" + to.getName() + "\" doesn't exist"); - - std::map<std::pair<State, regexp::RegExp>, State> transitionsToState; - for (std::map<std::pair<State, regexp::RegExp>, State>::const_iterator transition = transitions.begin(); transition != transitions.end(); - transition++) { - if (transition->second == to) { - transitionsToState.insert(make_pair(transition->first, transition->second)); - } - } - - return transitionsToState; -} - -} /* namespace automaton */ diff --git a/alib2/src/automaton/FSM/ExtendedNFA.cpp b/alib2/src/automaton/FSM/ExtendedNFA.cpp new file mode 100644 index 0000000000000000000000000000000000000000..796d32ab95c61b7d185cd222edbea7a6e0f6846a --- /dev/null +++ b/alib2/src/automaton/FSM/ExtendedNFA.cpp @@ -0,0 +1,99 @@ +/* + * ExtendedNFA.cpp + * + * Created on: Mar 25, 2013 + * Author: Jan Travnicek + */ + +#include "ExtendedNFA.h" +#include "../AutomatonException.h" +#include <ostream> +#include <algorithm> + +namespace automaton { + +bool ExtendedNFA::removeState(const State& state) { + if (initialStates.find(state) != initialStates.end()) { + throw AutomatonException("State \"" + state.getName() + "\" is initial state."); + } + + if (finalStates.find(state) != finalStates.end()) { + throw AutomatonException("State \"" + state.getName() + "\" is final state."); + } + + for (std::map<std::pair<State, regexp::RegExp>, std::set<State> >::const_iterator t = transitions.begin(); t != transitions.end(); t++) { + if (t->first.first == state || t->second.find(state) != t->second.end()) + throw AutomatonException("State \"" + state.getName() + "\" is used in transition."); + } + + return states.erase(state); +} + +bool ExtendedNFA::removeInputSymbol(const alphabet::Symbol& symbol) { + for (std::map<std::pair<State, regexp::RegExp>, std::set<State> >::const_iterator transition = transitions.begin(); transition != transitions.end(); + transition++) { + if (transition->first.second.getAlphabet().count(symbol) == 1) + throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" is used."); + } + + return inputAlphabet.erase(symbol); +} + +bool ExtendedNFA::addTransition(const State& from, const regexp::RegExp& input, const State& to) { + if (states.find(from) == states.end()) + throw AutomatonException("State \"" + from.getName() + "\" doesn't exist."); + + std::set<alphabet::Symbol> inputRegExpAlphabet; + std::set_symmetric_difference(inputAlphabet.begin(), inputAlphabet.end(), input.getAlphabet().begin(), input.getAlphabet().end(), std::inserter(inputRegExpAlphabet, inputRegExpAlphabet.end())); + if (inputRegExpAlphabet.size() != 0) + throw AutomatonException("Input string is over different alphabet than automaton"); + + if (states.find(to) == states.end()) + throw AutomatonException("State \"" + to.getName() + "\" doesn't exist."); + + std::pair<State, regexp::RegExp> key = make_pair(from, input); + + return transitions[key].insert(to).second; +} + +bool ExtendedNFA::removeTransition(const State& from, const regexp::RegExp& input, const State& to) { + std::pair<State, regexp::RegExp> key = make_pair(from, input); + + return transitions[key].erase(to); +} + +const std::map<std::pair<State, regexp::RegExp>, std::set<State> >& ExtendedNFA::getTransitions() const { + return transitions; +} + +std::map<std::pair<State, regexp::RegExp>, std::set<State> > ExtendedNFA::getTransitionsFromState(const State& from) const { + if( states.find(from) == states.end()) + throw AutomatonException("State \"" + from.getName() + "\" doesn't exist"); + + std::map<std::pair<State, regexp::RegExp>, std::set<State>> transitionsFromState; + for (std::map<std::pair<State, regexp::RegExp>, std::set<State> >::const_iterator transition = transitions.begin(); transition != transitions.end(); + transition++) { + if (transition->first.first == from) { + transitionsFromState.insert(make_pair(transition->first, transition->second)); + } + } + + return transitionsFromState; +} + +std::map<std::pair<State, regexp::RegExp>, std::set<State> > ExtendedNFA::getTransitionsToState(const State& to) const { + if( states.find(to) == states.end()) + throw AutomatonException("State \"" + to.getName() + "\" doesn't exist"); + + std::map<std::pair<State, regexp::RegExp>, std::set<State>> transitionsToState; + for (std::map<std::pair<State, regexp::RegExp>, std::set<State> >::const_iterator transition = transitions.begin(); transition != transitions.end(); + transition++) { + if (transition->second.find(to) != transition->second.end()) { + transitionsToState.insert(make_pair(transition->first, transition->second)); + } + } + + return transitionsToState; +} + +} /* namespace automaton */ diff --git a/alib2/src/automaton/FSM/ExtendedFA.h b/alib2/src/automaton/FSM/ExtendedNFA.h similarity index 57% rename from alib2/src/automaton/FSM/ExtendedFA.h rename to alib2/src/automaton/FSM/ExtendedNFA.h index d34a3f7ff2d0c4856d7513ffcd1327933b54a5e5..e9cc2712e7d0818458ba36c91401b5ce27c7ffb4 100644 --- a/alib2/src/automaton/FSM/ExtendedFA.h +++ b/alib2/src/automaton/FSM/ExtendedNFA.h @@ -1,15 +1,16 @@ /* - * ExtendedFA.h + * ExtendedNFA.h * * Created on: Mar 25, 2013 * Author: Jan Travnicek */ -#ifndef EXTENDED_FA_H_ -#define EXTENDED_FA_H_ +#ifndef EXTENDED_NFA_H_ +#define EXTENDED_NFA_H_ #include <map> -#include "../Automaton.h" +#include "../NondeterministicAutomaton.h" +#include "../InputAlphabet.h" #include "../State.h" #include "../../regexp/RegExp.h" @@ -19,24 +20,19 @@ namespace automaton { * Represents Finite Automaton. * Can store nondeterministic finite automaton without epsilon transitions. */ -class ExtendedFA : public Automaton { +class ExtendedNFA : public NondeterministicAutomaton, public InputAlphabet { protected: - std::map<std::pair<State, regexp::RegExp>, State> transitions; + std::map<std::pair<State, regexp::RegExp>, std::set<State> > transitions; public: - /** - * @copydoc Automaton::addInputSymbol(const Symbol&) - */ - virtual void addInputSymbol(const alphabet::Symbol& symbol); - /** * @copydoc Automaton::removeState(const State&) */ - virtual void removeState(const State& state); + virtual bool removeState(const State& state); /** * @copydoc Automaton::removeInputSymbol(const Symbol&) */ - virtual void removeInputSymbol(const alphabet::Symbol& symbol); + virtual bool removeInputSymbol(const alphabet::Symbol& symbol); /** * Adds transition defined by parameters to the automaton. @@ -45,33 +41,33 @@ public: * @param next next state * @throws AutomatonException when transition already exists or when transition contains state or symbol not present in the automaton */ - void addTransition(const State& current, const regexp::RegExp& input, const State& next); + bool addTransition(const State& current, const regexp::RegExp& input, const State& next); /** * Removes transition from the automaton. * @param transition transition to remove * @throws AutomatonException when transition doesn't exists. */ - void removeTransition(const State& current, const regexp::RegExp& input, const State& next); + bool removeTransition(const State& current, const regexp::RegExp& input, const State& next); /** * @return automaton transitions */ - const std::map<std::pair<State, regexp::RegExp>, State>& getTransitions() const; + const std::map<std::pair<State, regexp::RegExp>, std::set<State> >& getTransitions() const; /** * @return automaton transitions from state */ - std::map<std::pair<State, regexp::RegExp>, State> getTransitionsFromState(const State& from) const; + std::map<std::pair<State, regexp::RegExp>, std::set<State> > getTransitionsFromState(const State& from) const; /** * @return automaton transitions to state */ - std::map<std::pair<State, regexp::RegExp>, State> getTransitionsToState(const State& from) const; + std::map<std::pair<State, regexp::RegExp>, std::set<State> > getTransitionsToState(const State& from) const; - friend std::ostream& operator<<(std::ostream& out, const ExtendedFA& automaton); + friend std::ostream& operator<<(std::ostream& out, const ExtendedNFA& automaton); }; } /* namespace automaton */ -#endif /* EXTENDED_FA_H_ */ +#endif /* EXTENDED_NFA_H_ */ diff --git a/alib2/src/automaton/FSM/FSM.cpp b/alib2/src/automaton/FSM/FSM.cpp deleted file mode 100644 index 18ff23b4717eb7e473cfa408dc35895b03696adb..0000000000000000000000000000000000000000 --- a/alib2/src/automaton/FSM/FSM.cpp +++ /dev/null @@ -1,20 +0,0 @@ -/* - * FSM.cpp - * - * Created on: Mar 25, 2013 - * Author: Jan Travnicek - */ - -#include "FSM.h" -#include "../AutomatonException.h" -#include <ostream> - -namespace automaton { - -void FSM::addInputSymbol(const alphabet::Symbol& symbol) { - std::pair<std::set<alphabet::Symbol>::iterator, bool> ret = inputAlphabet.insert(symbol); - if (!ret.second) - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" already exists."); -} - -} /* namespace automaton */ diff --git a/alib2/src/automaton/FSM/FSM.h b/alib2/src/automaton/FSM/FSM.h deleted file mode 100644 index ddf21a84a6b7b060c9d3471866156e3fbb2da057..0000000000000000000000000000000000000000 --- a/alib2/src/automaton/FSM/FSM.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * FSM.h - * - * Created on: Mar 25, 2013 - * Author: Jan Travnicek - */ - -#ifndef FSM_H_ -#define FSM_H_ - -#include <map> -#include "../Automaton.h" -#include "../State.h" -#include "../../alphabet/Symbol.h" - -namespace automaton { - -/** - * Represents Finite Automaton. - */ -class FSM : public Automaton { -public: - /** - * @copydoc Automaton::addInputSymbol(const Symbol&) - */ - virtual void addInputSymbol(const alphabet::Symbol& symbol); - -}; - -} /* namespace automaton */ - -#endif /* FSM_H_ */ diff --git a/alib2/src/automaton/FSM/FSMFromXMLParser.cpp b/alib2/src/automaton/FSM/FSMFromXMLParser.cpp index 7a2597f149ed1d91372b56752e31adef89a6e48c..fe2b45e8db344ea034a6948386231032b1488686 100644 --- a/alib2/src/automaton/FSM/FSMFromXMLParser.cpp +++ b/alib2/src/automaton/FSM/FSMFromXMLParser.cpp @@ -12,7 +12,7 @@ namespace automaton { -FSM* FSMFromXMLParser::parse(std::list<sax::Token> &input) { +Automaton* FSMFromXMLParser::parse(std::list<sax::Token> &input) { if(isToken(input, sax::Token::START_ELEMENT, "EpsilonNFA")) return new EpsilonNFA(parseEpsilonNFA(input)); else if(isToken(input, sax::Token::START_ELEMENT, "NFA")) @@ -24,80 +24,106 @@ FSM* FSMFromXMLParser::parse(std::list<sax::Token> &input) { } DFA FSMFromXMLParser::parseDFA(std::list<sax::Token>& input) { - DFA automaton; + popToken(input, sax::Token::START_ELEMENT, "DFA"); - popToken(input, sax::Token::START_ELEMENT, "EpsilonNFA"); + std::set<State> states = parseStates(input); + std::set<alphabet::Symbol> inputSymbols = parseInputAlphabet(input); + State initialState = parseInitialState(input); + std::set<State> finalStates = parseFinalStates(input); + + DFA automaton(initialState); + automaton.setStates(states); + automaton.setInputSymbols(inputSymbols); + automaton.setFinalStates(finalStates); - parseStates(input, automaton); - parseInputAlphabet(input, automaton); - parseInitialStates(input, automaton); - parseFinalStates(input, automaton); parseTransitions<DFA>(input, automaton); - popToken(input, sax::Token::END_ELEMENT, "EpsilonNFA"); + popToken(input, sax::Token::END_ELEMENT, "DFA"); return automaton; } NFA FSMFromXMLParser::parseNFA(std::list<sax::Token>& input) { - NFA automaton; + popToken(input, sax::Token::START_ELEMENT, "NFA"); - popToken(input, sax::Token::START_ELEMENT, "EpsilonNFA"); + std::set<State> states = parseStates(input); + std::set<alphabet::Symbol> inputSymbols = parseInputAlphabet(input); + std::set<State> initialStates = parseInitialStates(input); + std::set<State> finalStates = parseFinalStates(input); + + NFA automaton; + automaton.setStates(states); + automaton.setInputSymbols(inputSymbols); + automaton.setInitialStates(initialStates); + automaton.setFinalStates(finalStates); - parseStates(input, automaton); - parseInputAlphabet(input, automaton); - parseInitialStates(input, automaton); - parseFinalStates(input, automaton); parseTransitions<NFA>(input, automaton); - popToken(input, sax::Token::END_ELEMENT, "EpsilonNFA"); + popToken(input, sax::Token::END_ELEMENT, "NFA"); return automaton; } EpsilonNFA FSMFromXMLParser::parseEpsilonNFA(std::list<sax::Token>& input) { - EpsilonNFA automaton; - popToken(input, sax::Token::START_ELEMENT, "EpsilonNFA"); - parseStates(input, automaton); - parseInputAlphabet(input, automaton); - parseInitialStates(input, automaton); - parseFinalStates(input, automaton); + std::set<State> states = parseStates(input); + std::set<alphabet::Symbol> inputSymbols = parseInputAlphabet(input); + std::set<State> initialStates = parseInitialStates(input); + std::set<State> finalStates = parseFinalStates(input); + + EpsilonNFA automaton; + automaton.setStates(states); + automaton.setInputSymbols(inputSymbols); + automaton.setInitialStates(initialStates); + automaton.setFinalStates(finalStates); + parseTransitions<EpsilonNFA>(input, automaton); popToken(input, sax::Token::END_ELEMENT, "EpsilonNFA"); return automaton; } -void FSMFromXMLParser::parseStates(std::list<sax::Token> &input, FSM& automaton) { +std::set<State> FSMFromXMLParser::parseStates(std::list<sax::Token> &input) { + std::set<State> states; popToken(input, sax::Token::START_ELEMENT, "states"); while (isToken(input, sax::Token::START_ELEMENT, "state")) { - automaton.addState(parseState(input, "state")); + states.insert(parseState(input, "state")); } popToken(input, sax::Token::END_ELEMENT, "states"); + return states; } -void FSMFromXMLParser::parseInputAlphabet(std::list<sax::Token> &input, FSM& automaton) { +std::set<alphabet::Symbol> FSMFromXMLParser::parseInputAlphabet(std::list<sax::Token> &input) { + std::set<alphabet::Symbol> inputSymbols; popToken(input, sax::Token::START_ELEMENT, "inputAlphabet"); while (isToken(input, sax::Token::START_ELEMENT, "symbol")) { - automaton.addInputSymbol(parseSymbol(input, "symbol")); + inputSymbols.insert(parseSymbol(input, "symbol")); } popToken(input, sax::Token::END_ELEMENT, "inputAlphabet"); + return inputSymbols; +} + +State FSMFromXMLParser::parseInitialState(std::list<sax::Token> &input) { + return parseState(input, "initialState"); } -void FSMFromXMLParser::parseInitialStates(std::list<sax::Token> &input, FSM& automaton) { +std::set<State> FSMFromXMLParser::parseInitialStates(std::list<sax::Token> &input) { + std::set<State> initialStates; popToken(input, sax::Token::START_ELEMENT, "initialStates"); while (isToken(input, sax::Token::START_ELEMENT, "state")) { - automaton.addInitialState(parseState(input, "state")); + initialStates.insert(parseState(input, "state")); } popToken(input, sax::Token::END_ELEMENT, "initialStates"); + return initialStates; } -void FSMFromXMLParser::parseFinalStates(std::list<sax::Token> &input, FSM& automaton) { +std::set<State> FSMFromXMLParser::parseFinalStates(std::list<sax::Token> &input) { + std::set<State> finalStates; popToken(input, sax::Token::START_ELEMENT, "finalStates"); while (isToken(input, sax::Token::START_ELEMENT, "state")) { - automaton.addFinalState(parseState(input, "state")); + finalStates.insert(parseState(input, "state")); } popToken(input, sax::Token::END_ELEMENT, "finalStates"); + return finalStates; } template<class T> diff --git a/alib2/src/automaton/FSM/FSMFromXMLParser.h b/alib2/src/automaton/FSM/FSMFromXMLParser.h index 1fa3023247d28c69c68ee8ea5fed7b3938935a5f..d51ec5ff7ab379fc05d3da35b3c4e9c092df34c2 100644 --- a/alib2/src/automaton/FSM/FSMFromXMLParser.h +++ b/alib2/src/automaton/FSM/FSMFromXMLParser.h @@ -9,7 +9,6 @@ #define FSM_FROM_XML_PARSER_H_ #include "../../sax/FromXMLParser.h" -#include "FSM.h" #include "EpsilonNFA.h" #include "NFA.h" #include "DFA.h" @@ -26,10 +25,11 @@ namespace automaton { */ class FSMFromXMLParser : public sax::FromXMLParser { protected: - void parseStates(std::list<sax::Token> &input, FSM& automaton); - void parseInputAlphabet(std::list<sax::Token> &input, FSM& automaton); - void parseInitialStates(std::list<sax::Token> &input, FSM& automaton); - void parseFinalStates(std::list<sax::Token> &input, FSM& automaton); + std::set<State> parseStates(std::list<sax::Token> &input); + std::set<alphabet::Symbol> parseInputAlphabet(std::list<sax::Token> &input); + State parseInitialState(std::list<sax::Token> &input); + std::set<State> parseInitialStates(std::list<sax::Token> &input); + std::set<State> parseFinalStates(std::list<sax::Token> &input); template<class T> void parseTransitions(std::list<sax::Token> &input, T& automaton); @@ -49,7 +49,7 @@ public: * @return UnknownAutomaton * @throws ParserException when an error occurs */ - FSM* parse(std::list<sax::Token> &input); + Automaton* parse(std::list<sax::Token> &input); EpsilonNFA parseEpsilonNFA(std::list<sax::Token>& input); NFA parseNFA(std::list<sax::Token>& input); diff --git a/alib2/src/automaton/FSM/FSMToXMLComposer.cpp b/alib2/src/automaton/FSM/FSMToXMLComposer.cpp index d8d0106d09a3d840c4a5e3ce4f2d4676d16fb847..a4221697253740f584ca60aaeb98292f2f087072 100644 --- a/alib2/src/automaton/FSM/FSMToXMLComposer.cpp +++ b/alib2/src/automaton/FSM/FSMToXMLComposer.cpp @@ -9,17 +9,17 @@ namespace automaton { -void FSMToXMLComposer::printStates(std::list<sax::Token>& out, const FSM& automaton, std::string tagName) { +void FSMToXMLComposer::printStates(std::list<sax::Token>& out, const std::set<State>& states, std::string tagName) { out.push_back(sax::Token(tagName, sax::Token::START_ELEMENT)); - for (auto& state : automaton.getStates()) { + for (auto& state : states) { printState(out, state, "state"); } out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT)); } -void FSMToXMLComposer::printSymbols(std::list<sax::Token>& out, const FSM& automaton, std::string tagName) { +void FSMToXMLComposer::printSymbols(std::list<sax::Token>& out, const std::set<alphabet::Symbol>& symbols, std::string tagName) { out.push_back(sax::Token(tagName, sax::Token::START_ELEMENT)); - for (auto& symbol : automaton.getInputAlphabet()) { + for (auto& symbol : symbols) { printSymbol(out, symbol, "symbol"); } out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT)); @@ -107,11 +107,11 @@ std::list<sax::Token> FSMToXMLComposer::compose(const DFA& automaton) { std::list<sax::Token> out; out.push_back(sax::Token("DFA", sax::Token::START_ELEMENT)); - printStates(out, automaton, "states"); - printSymbols(out, automaton, "inputAlphabet"); + printStates(out, automaton.getStates(), "states"); + printSymbols(out, automaton.getInputAlphabet(), "inputAlphabet"); + printState(out, automaton.getInitialState(), "initialState"); + printStates(out, automaton.getFinalStates(), "finalStates"); printTransitions(out, automaton); - printStates(out, automaton, "initialStates"); - printStates(out, automaton, "finalStates"); out.push_back(sax::Token("DFA", sax::Token::END_ELEMENT)); return out; @@ -121,11 +121,11 @@ std::list<sax::Token> FSMToXMLComposer::compose(const NFA& automaton) { std::list<sax::Token> out; out.push_back(sax::Token("NFA", sax::Token::START_ELEMENT)); - printStates(out, automaton, "states"); - printSymbols(out, automaton, "inputAlphabet"); + printStates(out, automaton.getStates(), "states"); + printSymbols(out, automaton.getInputAlphabet(), "inputAlphabet"); + printStates(out, automaton.getInitialStates(), "initialStates"); + printStates(out, automaton.getFinalStates(), "finalStates"); printTransitions(out, automaton); - printStates(out, automaton, "initialStates"); - printStates(out, automaton, "finalStates"); out.push_back(sax::Token("NFA", sax::Token::END_ELEMENT)); return out; @@ -135,11 +135,11 @@ std::list<sax::Token> FSMToXMLComposer::compose(const EpsilonNFA& automaton) { std::list<sax::Token> out; out.push_back(sax::Token("EpsilonNFA", sax::Token::START_ELEMENT)); - printStates(out, automaton, "states"); - printSymbols(out, automaton, "inputAlphabet"); + printStates(out, automaton.getStates(), "states"); + printSymbols(out, automaton.getInputAlphabet(), "inputAlphabet"); + printStates(out, automaton.getInitialStates(), "initialStates"); + printStates(out, automaton.getFinalStates(), "finalStates"); printTransitions(out, automaton); - printStates(out, automaton, "initialStates"); - printStates(out, automaton, "finalStates"); out.push_back(sax::Token("EpsilonNFA", sax::Token::END_ELEMENT)); return out; diff --git a/alib2/src/automaton/FSM/FSMToXMLComposer.h b/alib2/src/automaton/FSM/FSMToXMLComposer.h index 18d25194a11480485be1d14ea5e2645f9f928745..3aa332e2ee9a7e4d86d1659029b6d67642488135 100644 --- a/alib2/src/automaton/FSM/FSMToXMLComposer.h +++ b/alib2/src/automaton/FSM/FSMToXMLComposer.h @@ -5,8 +5,8 @@ * Author: Jan Travnicek */ -#ifndef AUTOMATON_TO_XML_COMPOSER_H_ -#define AUTOMATON_TO_XML_COMPOSER_H_ +#ifndef FSM_TO_XML_COMPOSER_H_ +#define FSM_TO_XML_COMPOSER_H_ #include <string> #include <list> @@ -22,8 +22,8 @@ namespace automaton { */ class FSMToXMLComposer { protected: - static void printStates(std::list<sax::Token>&, const FSM& automaton, std::string tagName); - static void printSymbols(std::list<sax::Token>&, const FSM& automaton, std::string tagName); + static void printStates(std::list<sax::Token>&, const std::set<State>& states, std::string tagName); + static void printSymbols(std::list<sax::Token>&, const std::set<alphabet::Symbol>& symbols, std::string tagName); static void printTransitions(std::list<sax::Token>&, const EpsilonNFA& automaton); static void printTransitions(std::list<sax::Token>&, const NFA& automaton); @@ -47,5 +47,5 @@ public: } /* namespace automaton */ -#endif /* AUTOMATON_TO_XML_COMPOSER_H_ */ +#endif /* FSM_TO_XML_COMPOSER_H_ */ diff --git a/alib2/src/automaton/FSM/NFA.cpp b/alib2/src/automaton/FSM/NFA.cpp index 5613bf085187f7ecde5a27f4782cd186f2a0c4f1..faa1235750da3a6c267224859a66b5bf72ea2d50 100644 --- a/alib2/src/automaton/FSM/NFA.cpp +++ b/alib2/src/automaton/FSM/NFA.cpp @@ -11,7 +11,7 @@ namespace automaton { -void NFA::removeState(const State& state) { +bool NFA::removeState(const State& state) { if (initialStates.find(state) != initialStates.end()) { throw AutomatonException("State \"" + state.getName() + "\" is initial state."); } @@ -25,25 +25,20 @@ void NFA::removeState(const State& state) { throw AutomatonException("State \"" + state.getName() + "\" is used in transition."); } - int removed = states.erase(state); - if (!removed) - throw AutomatonException("State \"" + state.getName() + "\" doesn't exist."); + return states.erase(state); } -void NFA::removeInputSymbol(const alphabet::Symbol& symbol) { +bool NFA::removeInputSymbol(const alphabet::Symbol& symbol) { for (std::map<std::pair<State, alphabet::Symbol>, std::set<State> >::const_iterator transition = transitions.begin(); transition != transitions.end(); transition++) { if (transition->first.second == symbol) throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" is used."); } - int removed = inputAlphabet.erase(symbol); - if (!removed) - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" doesn't exist."); - + return inputAlphabet.erase(symbol); } -void NFA::addTransition(const State& from, const alphabet::Symbol& input, const State& to) { +bool NFA::addTransition(const State& from, const alphabet::Symbol& input, const State& to) { if (states.find(from) == states.end()) throw AutomatonException("State \"" + from.getName() + "\" doesn't exist."); @@ -55,21 +50,13 @@ void NFA::addTransition(const State& from, const alphabet::Symbol& input, const std::pair<State, alphabet::Symbol> key = std::make_pair(from, input); - std::pair<std::set<automaton::State>::iterator, bool> ret = transitions[key].insert(to); - if (!ret.second) - throw AutomatonException( - "Transition (\"" + from.getName() + "\", \"" + input.getSymbol() + "\") -> \"" + to.getName() - + "\" already exists."); + return transitions[key].insert(to).second; } -void NFA::removeTransition(const State& from, const alphabet::Symbol& input, const State& to) { +bool NFA::removeTransition(const State& from, const alphabet::Symbol& input, const State& to) { std::pair<State, alphabet::Symbol> key = std::make_pair(from, input); - int removed = transitions[key].erase(to); - if (!removed) - throw AutomatonException( - "Transition (\"" + from.getName() + "\", \"" + input.getSymbol() - + "\") -> \"" + to.getName() + "\" doesn't exist."); + return transitions[key].erase(to); } const std::map<std::pair<State, alphabet::Symbol>, std::set<State> >& NFA::getTransitions() const { diff --git a/alib2/src/automaton/FSM/NFA.h b/alib2/src/automaton/FSM/NFA.h index dbd4bf5e2a3f7d2dc2ef2b100834759d98d77c3d..a223709dcd9eaa69f95714207da96a077e668318 100644 --- a/alib2/src/automaton/FSM/NFA.h +++ b/alib2/src/automaton/FSM/NFA.h @@ -9,7 +9,8 @@ #define NFA_H_ #include <map> -#include "FSM.h" +#include "../NondeterministicAutomaton.h" +#include "../InputAlphabet.h" #include "../State.h" #include "../../alphabet/Symbol.h" @@ -19,19 +20,19 @@ namespace automaton { * Represents Finite Automaton. * Can store nondeterministic finite automaton without epsilon transitions. */ -class NFA : public FSM { +class NFA : public NondeterministicAutomaton, public InputAlphabet { protected: std::map<std::pair<State, alphabet::Symbol>, std::set<State> > transitions; public: /** * @copydoc Automaton::removeState(const State&) */ - virtual void removeState(const State& state); + virtual bool removeState(const State& state); /** * @copydoc Automaton::removeInputSymbol(const Symbol&) */ - virtual void removeInputSymbol(const alphabet::Symbol& symbol); + virtual bool removeInputSymbol(const alphabet::Symbol& symbol); /** * Adds transition defined by parameters to the automaton. @@ -40,14 +41,14 @@ public: * @param next next state * @throws AutomatonException when transition already exists or when transition contains state or symbol not present in the automaton */ - void addTransition(const State& current, const alphabet::Symbol& input, const State& next); + bool addTransition(const State& current, const alphabet::Symbol& input, const State& next); /** * Removes transition from the automaton. * @param transition transition to remove * @throws AutomatonException when transition doesn't exists. */ - void removeTransition(const State& current, const alphabet::Symbol& input, const State& next); + bool removeTransition(const State& current, const alphabet::Symbol& input, const State& next); /** * @return automaton transitions diff --git a/alib2/src/automaton/InputAlphabet.cpp b/alib2/src/automaton/InputAlphabet.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04e3d594ba9739b5bd5548b539500b2870f8a6c3 --- /dev/null +++ b/alib2/src/automaton/InputAlphabet.cpp @@ -0,0 +1,40 @@ +/* + * InputAlphabet.cpp + * + * Created on: Apr 16, 2013 + * Author: Jan Travnicek + */ + +#include "InputAlphabet.h" + +#include <algorithm> +#include "AutomatonException.h" + +namespace automaton { + +const std::set<alphabet::Symbol>& InputAlphabet::getInputAlphabet() const { + return inputAlphabet; +} + +bool InputAlphabet::addInputSymbol(const alphabet::Symbol& symbol) { + return inputAlphabet.insert(symbol).second; +} + +void InputAlphabet::setInputSymbols(const std::set<alphabet::Symbol>& newSymbols) { + std::set<alphabet::Symbol> removed; + std::set_symmetric_difference(inputAlphabet.begin(), inputAlphabet.end(), newSymbols.begin(), newSymbols.end(), std::inserter(removed, removed.end())); + + std::set<alphabet::Symbol> added; + std::set_symmetric_difference(newSymbols.begin(), newSymbols.end(), inputAlphabet.begin(), inputAlphabet.end(), std::inserter(added, added.end())); + + for(const alphabet::Symbol& removedSymbol : removed) { + removeInputSymbol(removedSymbol); + } + + for(const alphabet::Symbol& addedSymbol : added) { + addInputSymbol(addedSymbol); + } +} + +} /* namespace automaton */ + diff --git a/alib2/src/automaton/InputAlphabet.h b/alib2/src/automaton/InputAlphabet.h new file mode 100644 index 0000000000000000000000000000000000000000..db92fe8b3c6214fa9cedf79a51b8a01b9b9ebb96 --- /dev/null +++ b/alib2/src/automaton/InputAlphabet.h @@ -0,0 +1,56 @@ +/* + * InputAutomaton.h + * + * Created on: Apr 10, 2013 + * Author: Jan Travnicek + */ + +#ifndef INPUT_ALPHABET_H_ +#define INPUT_ALPHABET_H_ + +#include <set> +#include "../alphabet/Symbol.h" + + +namespace automaton { + +/** + * Abstract base class for all automatons. Contains common elements of automatons. + */ +class InputAlphabet { +protected: + std::set<alphabet::Symbol> inputAlphabet; +public: + /** + * Adds input symbol to input alphabet. + * @param symbol Symbol to add + * @throws AutomatonException when symbol already exists + */ + bool addInputSymbol(const alphabet::Symbol& symbol); + + /** + * Sets input symbols of the automaton. + * @param symbols Symbols to set + * @throws AutomatonException when symbol already exists + */ + void setInputSymbols(const std::set<alphabet::Symbol>& symbols); + + /** + * Removes input symbol from the input alphabet. + * @param symbol Symbol to remove + * @throws AutomatonException when symbol is not present in input alphabet + * or when symbol is part of the transition + */ + virtual bool removeInputSymbol(const alphabet::Symbol& symbol) = 0; + + /** + * @return the input alphabet + */ + const std::set<alphabet::Symbol>& getInputAlphabet() const; + +}; + +} /* namespace automaton */ + +#endif /* INPUT_ALPHABET_H_ */ + diff --git a/alib2/src/automaton/NondeterministicAutomaton.cpp b/alib2/src/automaton/NondeterministicAutomaton.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c6a0daf38f21b707d984337677f5cb43a78e028f --- /dev/null +++ b/alib2/src/automaton/NondeterministicAutomaton.cpp @@ -0,0 +1,49 @@ +/* + * NondeterministicAutomaton.cpp + * + * Created on: Apr 16, 2013 + * Author: Jan Travnicek + */ + +#include "NondeterministicAutomaton.h" + +#include <set> +#include <algorithm> +#include "AutomatonException.h" + +namespace automaton { + +bool NondeterministicAutomaton::addInitialState(const State& state) { + if (states.find(state) == states.end()) { + throw AutomatonException("State cannot be set as initial state. It is not present in the automaton."); + } + + return initialStates.insert(state).second; +} + +void NondeterministicAutomaton::setInitialStates(const std::set<State>& newStates) { + std::set<State> removed; + std::set_symmetric_difference(initialStates.begin(), initialStates.end(), newStates.begin(), newStates.end(), std::inserter(removed, removed.end())); + + std::set<State> added; + std::set_symmetric_difference(newStates.begin(), newStates.end(), initialStates.begin(), initialStates.end(), std::inserter(added, added.end())); + + for(const State& removedState : removed) { + removeInitialState(removedState); + } + + for(const State& addedState : added) { + addInitialState(addedState); + } +} + +bool NondeterministicAutomaton::removeInitialState(const State& state) { + return initialStates.erase(state); +} + +const std::set<State>& NondeterministicAutomaton::getInitialStates() const { + return initialStates; +} + +} /* namespace automaton */ + diff --git a/alib2/src/automaton/NondeterministicAutomaton.h b/alib2/src/automaton/NondeterministicAutomaton.h new file mode 100644 index 0000000000000000000000000000000000000000..47517b958f0263b90cf4d573ff25d60d44983f57 --- /dev/null +++ b/alib2/src/automaton/NondeterministicAutomaton.h @@ -0,0 +1,56 @@ +/* + * Automaton.h + * + * Created on: Apr 10, 2013 + * Author: Jan Travnicek + */ + +#ifndef NONDETERMINISTIC_AUTOMATON_H_ +#define NONDETERMINISTIC_AUTOMATON_H_ + +#include "Automaton.h" +#include <set> +#include "State.h" + +namespace automaton { + +/** + * Base class for nondeterministic automata. + */ +class NondeterministicAutomaton : public Automaton { +protected: + std::set<State> initialStates; +public: + /** + * Adds the State to the initial states. + * @param state State to add + * @throws AutomatonException when state is not present + * in the automaton or when it's already initial state + */ + bool addInitialState(const State& state); + + /** + * Sets the initial state of the automaton. + * @param state State to add + * @throws AutomatonException when state is not present + * in the automaton or when it's already initial state + */ + void setInitialStates(const std::set<State>& states); + + /** + * Removes the state from the initial states. + * @param state State to remove + * @throws AutomatonException when State is not initial state + */ + bool removeInitialState(const State& state); + + /** + * @return initial states + */ + const std::set<State>& getInitialStates() const; +}; + +} /* namespace automaton */ + +#endif /* NONDETERMINISTIC_AUTOMATON_H_ */ + diff --git a/alib2/src/automaton/PDA/PDA.cpp b/alib2/src/automaton/PDA/PDA.cpp index 5fac6f78fc42955fcdb1e7d4eb6ff89ce165bfd7..aef4aa46eb67df7a1d288ea31e6e29a6f1b006f2 100644 --- a/alib2/src/automaton/PDA/PDA.cpp +++ b/alib2/src/automaton/PDA/PDA.cpp @@ -11,13 +11,7 @@ namespace automaton { -void PDA::addInputSymbol(const alphabet::Symbol& symbol) { - std::pair<std::set<alphabet::Symbol>::iterator, bool> ret = inputAlphabet.insert(symbol); - if (!ret.second) - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" already exists."); -} - -void PDA::removeState(const State& state) { +bool PDA::removeState(const State& state) { if (initialStates.find(state) != initialStates.end()) { throw AutomatonException("State \"" + state.getName() + "\" is initial state."); } @@ -35,29 +29,39 @@ void PDA::removeState(const State& state) { } } - int removed = states.erase(state); - if (!removed) - throw AutomatonException("State \"" + state.getName() + "\" doesn't exist."); + return states.erase(state); } -void PDA::removeInputSymbol(const alphabet::Symbol& symbol) { +bool PDA::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 \"" + symbol.getSymbol() + "\" is used in transition."); } - int removed = inputAlphabet.erase(symbol); - if (!removed) - throw AutomatonException("Symbol \"" + symbol.getSymbol() + "\" doesn't exist."); + return inputAlphabet.erase(symbol); +} + +bool PDA::addStackSymbol(const alphabet::Symbol& symbol) { + return stackAlphabet.insert(symbol).second; } -void PDA::addStackSymbol(const alphabet::Symbol& symbol) { - std::pair<std::set<alphabet::Symbol>::iterator, bool> ret = stackAlphabet.insert(symbol); - if (!ret.second) - throw AutomatonException("Stack symbol \"" + symbol.getSymbol() + "\" already exists."); +void PDA::setStackSymbols(const std::set<alphabet::Symbol>& newSymbols) { + std::set<alphabet::Symbol> removed; + std::set_symmetric_difference(stackAlphabet.begin(), stackAlphabet.end(), newSymbols.begin(), newSymbols.end(), std::inserter(removed, removed.end())); + + std::set<alphabet::Symbol> added; + std::set_symmetric_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); + } } -void PDA::removeStackSymbol(const alphabet::Symbol& symbol) { +bool PDA::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++) { @@ -74,17 +78,14 @@ void PDA::removeStackSymbol(const alphabet::Symbol& symbol) { throw AutomatonException("Stack symbol \"" + symbol.getSymbol() + "\" is start symbol."); } - int removed = stackAlphabet.erase(symbol); - if (!removed) - throw AutomatonException("Stack symbol \"" + symbol.getSymbol() + "\" doesn't exist."); - + return stackAlphabet.erase(symbol); } const std::set<alphabet::Symbol>& PDA::getStackAlphabet() const { return stackAlphabet; } -void 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 PDA::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 \"" + from.getName() + "\" doesn't exist."); } @@ -115,52 +116,36 @@ void PDA::addTransition(const State& from, const alphabet::Symbol& input, const std::pair<automaton::State, std::vector<alphabet::Symbol> > value = std::make_pair(to, push); - std::pair<std::set<std::pair<automaton::State, std::vector<alphabet::Symbol> > >::iterator, bool> ret = transitions[key].insert(value); - if (!ret.second) { - throw AutomatonException("Transition already exists."); - } + return transitions[key].insert(value).second; } -void 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 PDA::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); std::pair<automaton::State, std::vector<alphabet::Symbol> > value = std::make_pair(to, push); - int removed = transitions[key].erase(value); - if (!removed) { - throw AutomatonException("Transition doesn't exist."); - } + 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 { return transitions; } -void PDA::addInitialSymbol(const alphabet::Symbol& start) { +bool PDA::addInitialSymbol(const alphabet::Symbol& start) { if (stackAlphabet.find(start) == stackAlphabet.end()) { throw AutomatonException("Stack symbol \"" + start.getSymbol() + "\" doesn't exist."); } - std::pair<std::set<alphabet::Symbol>::iterator, bool> ret = this->initialSymbols.insert(start); - if (!ret.second) { - throw AutomatonException("Transition already exists."); - } + return this->initialSymbols.insert(start).second; } -void PDA::removeInitialSymbol(const alphabet::Symbol& start) { - if(this->initialSymbols.size() <= 1) - throw AutomatonException("There must be at least one initial symbol"); - int removed = this->initialSymbols.erase(start); - if (!removed) - throw AutomatonException("Transition doesn't exist."); +bool PDA::removeInitialSymbol(const alphabet::Symbol& start) { + return this->initialSymbols.erase(start); } void PDA::setInitialSymbols(const std::set<alphabet::Symbol>& symbols) { - if(symbols.size() < 1) - throw AutomatonException("There must be at least one initial symbol"); - std::set<alphabet::Symbol> tmp; std::set_symmetric_difference(symbols.begin(), symbols.end(), this->stackAlphabet.begin(), this->stackAlphabet.end(), std::inserter(tmp, tmp.end())); if(tmp.size() != 0) diff --git a/alib2/src/automaton/PDA/PDA.h b/alib2/src/automaton/PDA/PDA.h index e767112b4c10a886350659d0de46e49f542fee9f..472873d97738e396018c1c01b38d744ecc94afe0 100644 --- a/alib2/src/automaton/PDA/PDA.h +++ b/alib2/src/automaton/PDA/PDA.h @@ -12,7 +12,8 @@ #include <map> #include <vector> #include "../../std/variant.hpp" -#include "../Automaton.h" +#include "../NondeterministicAutomaton.h" +#include "../InputAlphabet.h" #include "../State.h" #include "../../alphabet/Symbol.h" #include "../../string/Epsilon.h" @@ -22,33 +23,35 @@ namespace automaton { /** * Push Down Automaton */ -class PDA: public Automaton { +class PDA: public NondeterministicAutomaton, 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; std::set<alphabet::Symbol> initialSymbols; public: - /** - * @copydoc Automaton::addInputSymbol(const Symbol&) - */ - virtual void addInputSymbol(const alphabet::Symbol& symbol); - /** * @copydoc Automaton::removeState(const State&) */ - virtual void removeState(const State& state); + virtual bool removeState(const State& state); /** * @copydoc Automaton::removeInputSymbol(const Symbol&) */ - virtual void removeInputSymbol(const alphabet::Symbol& 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 */ - void addStackSymbol(const alphabet::Symbol& symbol); + 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. @@ -57,7 +60,7 @@ public: * (popped from or pushed to the stack), when it is a start symbol * or when it is not present in the stack alphabet */ - void removeStackSymbol(const alphabet::Symbol& symbol); + bool removeStackSymbol(const alphabet::Symbol& symbol); /** * @return the stack alphabet @@ -70,14 +73,14 @@ public: * @throws AutomatonException when some part of the transition is not present * in the PDA (state, input symbol, stack symbol) or when transition already exists */ - void 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. * @param transition transition to remove * @throws AutomatonException when transition is not present in the PDA */ - void 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 @@ -90,7 +93,7 @@ public: * @param start new initial symbol * @throws AutomatonException when symbol is not present in the stack alphabet or it is already in the set */ - void addInitialSymbol(const alphabet::Symbol& start); + bool addInitialSymbol(const alphabet::Symbol& start); /** @@ -99,7 +102,7 @@ public: * @param start new initial symbol * @throws AutomatonException when symbol is not present in the set of initial symbols */ - void removeInitialSymbol(const alphabet::Symbol& start); + bool removeInitialSymbol(const alphabet::Symbol& start); /** * Sets initial symbols. Initial symbols are symbols that are pushed diff --git a/alib2/src/automaton/TM/OneTapeDTM.cpp b/alib2/src/automaton/TM/OneTapeDTM.cpp index 4dca1a31af8924490fbeaa2339d6ec5550b5b783..d52df57d50eb7abd992d7378a3ea131c9dfdaa3a 100644 --- a/alib2/src/automaton/TM/OneTapeDTM.cpp +++ b/alib2/src/automaton/TM/OneTapeDTM.cpp @@ -14,26 +14,11 @@ namespace automaton { using namespace std; using namespace alphabet; -OneTapeDTM::OneTapeDTM() : blankSymbol(Blank()) { - tapeAlphabet.insert(blankSymbol); +OneTapeDTM::OneTapeDTM(const State& initialState, const alphabet::Symbol& blank) : DeterministicAutomaton(initialState), BlankSymbolInputTapeAlphabet(blank) { } -void OneTapeDTM::addInputSymbol(const alphabet::Symbol& symbol) { - if (tapeAlphabet.find(symbol) == tapeAlphabet.end()) { - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" is not in tape alphabet."); - } - - if (symbol == blankSymbol) { - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" cannot be blank symbol."); - } - - std::pair<std::set<alphabet::Symbol>::iterator, bool> ret = inputAlphabet.insert(symbol); - if (!ret.second) - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" already exists."); -} - -void OneTapeDTM::removeState(const State& state) { - if (initialStates.find(state) != initialStates.end()) { +bool OneTapeDTM::removeState(const State& state) { + if (initialState == state) { throw AutomatonException("State \"" + state.getName() + "\" is initial state."); } @@ -46,24 +31,14 @@ void OneTapeDTM::removeState(const State& state) { throw AutomatonException("State \"" + state.getName() + "\" is used in a transition."); } - int removed = states.erase(state); - if (!removed) - throw AutomatonException("State \"" + state.getName() + "\" doesn't exist."); + return states.erase(state); } -void OneTapeDTM::removeInputSymbol(const alphabet::Symbol& symbol) { - int removed = inputAlphabet.erase(symbol); - if (!removed) - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" doesn't exist."); +bool OneTapeDTM::removeInputSymbol(const alphabet::Symbol& symbol) { + return inputAlphabet.erase(symbol); } -void OneTapeDTM::addTapeSymbol(const alphabet::Symbol& symbol) { - std::pair<std::set<alphabet::Symbol>::iterator, bool> ret = tapeAlphabet.insert(symbol); - if (!ret.second) - throw AutomatonException("Tape symbol \"" + symbol.getSymbol() + "\" already exists."); -} - -void OneTapeDTM::removeTapeSymbol(const alphabet::Symbol& symbol) { +bool OneTapeDTM::removeTapeSymbol(const alphabet::Symbol& symbol) { if (inputAlphabet.find(symbol) != inputAlphabet.end()) { throw AutomatonException("Tape symbol \"" + symbol.getSymbol() + "\" is in input alphabet."); } @@ -73,17 +48,10 @@ void OneTapeDTM::removeTapeSymbol(const alphabet::Symbol& symbol) { throw AutomatonException("Tape symbol \"" + symbol.getSymbol() + "\" is used in transition."); } - int removed = inputAlphabet.erase(symbol); - if (!removed) - throw AutomatonException("Tape symbol \"" + symbol.getSymbol() + "\" doesn't exist."); - -} - -const std::set<alphabet::Symbol>& OneTapeDTM::getTapeAlphabet() const { - return tapeAlphabet; + return inputAlphabet.erase(symbol); } -void OneTapeDTM::addTransition(const State& from, const alphabet::Symbol& input, const State& to, const alphabet::Symbol& output, const Shift& shift) { +bool OneTapeDTM::addTransition(const State& from, const alphabet::Symbol& input, const State& to, const alphabet::Symbol& output, const Shift& shift) { if (states.find(from) == states.end()) { throw AutomatonException("State \"" + from.getName() + "\" doesn't exist."); } @@ -106,39 +74,35 @@ void OneTapeDTM::addTransition(const State& from, const alphabet::Symbol& input, std::tuple<State, alphabet::Symbol, Shift > value(to, output, shift); - if (transitions.find(key) != transitions.end()) - throw AutomatonException( + if (transitions.find(key) != transitions.end()) { + if(transitions.find(key)->second == value) + return false; + else + throw AutomatonException( "Transition (\"" + from.getName() + "\", \"" + input.getSymbol() + "\") -> ? already exists."); + } transitions.insert(std::make_pair(key, value)); + return true; } -void OneTapeDTM::removeTransition(const State& from, const alphabet::Symbol& input, const State& to, const alphabet::Symbol& output, const Shift& shift) { +bool OneTapeDTM::removeTransition(const State& from, const alphabet::Symbol& input, const State& to, const alphabet::Symbol& output, const Shift& shift) { std::pair<State, alphabet::Symbol> key = std::make_pair(from, input); if (transitions.find(key) == transitions.end()) + return false; + + std::tuple<State, alphabet::Symbol, Shift > value(to, output, shift); + if(transitions.find(key)->second != value) throw AutomatonException( "Transition (\"" + from.getName() + "\", \"" + input.getSymbol() + "\") -> ? doesn't exists."); transitions.erase(key); + return true; } const std::map<std::pair<State, alphabet::Symbol>, std::tuple<State, alphabet::Symbol, Shift> >& OneTapeDTM::getTransitions() const { return transitions; } -void OneTapeDTM::setBlankSymbol(const alphabet::Symbol& symbol) { - if (inputAlphabet.find(symbol) != inputAlphabet.end()) - throw AutomatonException("Blank symbol \"" + symbol.getSymbol() + "\" is in input alphabet."); - - if (tapeAlphabet.find(symbol) == tapeAlphabet.end()) - throw AutomatonException("Blank symbol \"" + symbol.getSymbol() + "\" is not in tape alphabet."); - - blankSymbol = symbol; - -} -const alphabet::Symbol& OneTapeDTM::getBlankSymbol() const { - return blankSymbol; -} - } /* namespace automaton */ diff --git a/alib2/src/automaton/TM/OneTapeDTM.h b/alib2/src/automaton/TM/OneTapeDTM.h index 5d009369dde3422e2a79b9895f307cae884b0606..3403c24ec104eb37d3e8df13cc81c3c05479489d 100644 --- a/alib2/src/automaton/TM/OneTapeDTM.h +++ b/alib2/src/automaton/TM/OneTapeDTM.h @@ -8,7 +8,8 @@ #ifndef ONE_TAPE_DTM_H_ #define ONE_TAPE_DTM_H_ -#include "../Automaton.h" +#include "../DeterministicAutomaton.h" +#include "../BlankSymbolInputTapeAlphabet.h" #include "../Shift.h" #include <map> @@ -20,41 +21,24 @@ namespace automaton { /** * One tape turing machine */ -class OneTapeDTM : public Automaton { +class OneTapeDTM : public DeterministicAutomaton, public BlankSymbolInputTapeAlphabet { protected: - std::set<alphabet::Symbol> tapeAlphabet; std::map<std::pair<State, alphabet::Symbol>, std::tuple<State, alphabet::Symbol, Shift> > transitions; - alphabet::Symbol blankSymbol; public: - OneTapeDTM(); - - /** - * Adds symbol to the input alphabet. - * @param symbol Symbol to add - * @throws AutomatonException when symbol is not present in tape alphabet, - * when it's blank symbol or when it is already present in input alphabet - */ - virtual void addInputSymbol(const alphabet::Symbol& symbol); + OneTapeDTM(const State& initialState, const alphabet::Symbol& blank); /** * @copydoc Automaton::removeState(const State&) */ - virtual void removeState(const State& state); + virtual bool removeState(const State& state); /** * Removes input symbol from the input alphabet. * @param symbol Symbol to remove * @throws AutomatonException when symbol is part of the transition */ - virtual void removeInputSymbol(const alphabet::Symbol& symbol); - - /** - * Adds symbol to the tape alphabet. - * @param symbol Symbol to add - * @throw AutomatonException when Symbol is already present in tape alphabet - */ - void addTapeSymbol(const alphabet::Symbol& symbol); + virtual bool removeInputSymbol(const alphabet::Symbol& symbol); /** * Removes symbol from the tape alphabet. @@ -62,12 +46,7 @@ public: * @throw AutomatonException when Symbol is not present in the tape alphabet, * when it is used in transition or when it is present in input alphabet */ - void removeTapeSymbol(const alphabet::Symbol& symbol); - - /** - * @return tape alphabet - */ - const std::set<alphabet::Symbol>& getTapeAlphabet() const; + virtual bool removeTapeSymbol(const alphabet::Symbol& symbol); /** * Adds transition to the automaton. @@ -75,31 +54,20 @@ public: * @throws AutomatonException when some part of the transition is not present * in the TM (state, tape symbol) or when transition already exists */ - void addTransition(const State& from, const alphabet::Symbol& input, const State& to, const alphabet::Symbol& output, const Shift& shift); + bool addTransition(const State& from, const alphabet::Symbol& input, const State& to, const alphabet::Symbol& output, const Shift& shift); /** * Removes the transition from the TM. * @param transition transition to remove * @throws AutomatonException when transition is not present in the TM */ - void removeTransition(const State& from, const alphabet::Symbol& input, const State& to, const alphabet::Symbol& output, const Shift& shift); + bool removeTransition(const State& from, const alphabet::Symbol& input, const State& to, const alphabet::Symbol& output, const Shift& shift); /** * @return TM transitions */ const std::map<std::pair<State, alphabet::Symbol>, std::tuple<State, alphabet::Symbol, Shift> >& getTransitions() const; - /** - * Sets the blank symbol = symbol representing empty cell of the tape - * @param symbol Symbol to set - */ - void setBlankSymbol(const alphabet::Symbol& symbol); - - /** - * @return symbol representing empty cell of the tape - */ - const alphabet::Symbol& getBlankSymbol() const; - }; } /* namespace automaton */ diff --git a/alib2/src/automaton/UnknownAutomaton.cpp b/alib2/src/automaton/UnknownAutomaton.cpp index d8f79988a8cd39c36366cbede090e3cf5810162a..348a34ef9be1010b5cf3667b7bde879fa2184af9 100644 --- a/alib2/src/automaton/UnknownAutomaton.cpp +++ b/alib2/src/automaton/UnknownAutomaton.cpp @@ -2,7 +2,7 @@ * UnknownAutomaton.cpp * * Created on: Oct 12, 2013 - * Author: martin + * Author: Martin Zak */ #include "UnknownAutomaton.h" @@ -20,65 +20,97 @@ UnknownAutomaton::UnknownAutomaton() : UnknownAutomaton::~UnknownAutomaton() { } +bool UnknownAutomaton::addState(const State& state) { + return states.insert(state).second; +} + void UnknownAutomaton::setStates(const std::set<State>& states) { this->states = states; } -void UnknownAutomaton::removeState(const State& state) { - if (!states.erase(state)) - throw AutomatonException("State \"" + state.getName() + "\" doesn't exist."); +bool UnknownAutomaton::removeState(const State& state) { + return states.erase(state); +} + +const std::set<State>& UnknownAutomaton::getStates() const { + return states; } -void UnknownAutomaton::addInputSymbol(const alphabet::Symbol& symbol) { - if (!inputAlphabet.insert(symbol).second) { - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" already exists."); +bool UnknownAutomaton::addInitialState(const State& state) { + if (states.find(state) == states.end()) { + throw AutomatonException("State cannot be set as initial state. It is not present in the automaton."); } + + return initialStates.insert(state).second; +} + +bool UnknownAutomaton::removeInitialState(const State& state) { + return initialStates.erase(state); +} + +const std::set<State>& UnknownAutomaton::getInitialStates() const { + return initialStates; +} + + +bool UnknownAutomaton::addFinalState(const State& state) { + return finalStates.insert(state).second; +} + +bool UnknownAutomaton::removeFinalState(const State& state) { + return finalStates.erase(state); +} + +const std::set<State>& UnknownAutomaton::getFinalStates() const { + return finalStates; +} + + +bool UnknownAutomaton::addInputSymbol(const alphabet::Symbol& symbol) { + return inputAlphabet.insert(symbol).second; +} + +const std::set<alphabet::Symbol>& UnknownAutomaton::getInputSymbols() const { + return this->inputAlphabet; } void UnknownAutomaton::setInputSymbols(const std::set<alphabet::Symbol>& symbols) { this->inputAlphabet = symbols; } -void UnknownAutomaton::removeInputSymbol(const alphabet::Symbol& symbol) { - if (!inputAlphabet.erase(symbol)) - throw AutomatonException("Input symbol \"" + symbol.getSymbol() + "\" doesn't exist."); +bool UnknownAutomaton::removeInputSymbol(const alphabet::Symbol& symbol) { + return inputAlphabet.erase(symbol); } -void UnknownAutomaton::addStackSymbol(const alphabet::Symbol& symbol) { - if (!stackAlphabet.insert(symbol).second) { - throw AutomatonException("Stack symbol \"" + symbol.getSymbol() + "\" already exists."); - } +bool UnknownAutomaton::addStackSymbol(const alphabet::Symbol& symbol) { + return stackAlphabet.insert(symbol).second; } void UnknownAutomaton::setStackSymbols(const std::set<alphabet::Symbol>& symbols) { stackAlphabet = symbols; } -void UnknownAutomaton::removeStackSymbol(const alphabet::Symbol& symbol) { - if (!stackAlphabet.erase(symbol)) - throw AutomatonException("Stack symbol \"" + symbol.getSymbol() + "\" doesn't exist."); +bool UnknownAutomaton::removeStackSymbol(const alphabet::Symbol& symbol) { + return stackAlphabet.erase(symbol); } -const std::set<alphabet::Symbol>& UnknownAutomaton::getStackAlphabet() const { +const std::set<alphabet::Symbol>& UnknownAutomaton::getStackSymbols() const { return stackAlphabet; } -void UnknownAutomaton::addInitialSymbol(const alphabet::Symbol& symbol) { - if (!stackAlphabet.insert(symbol).second) { - throw AutomatonException("Stack symbol \"" + symbol.getSymbol() + "\" already exists."); - } +bool UnknownAutomaton::addInitialSymbol(const alphabet::Symbol& symbol) { + return stackAlphabet.insert(symbol).second; } void UnknownAutomaton::setInitialSymbols(const std::set<alphabet::Symbol>& symbols) { this->initialSymbols = symbols; } -void UnknownAutomaton::removeInitialSymbol(const alphabet::Symbol& symbol) { - if (!stackAlphabet.erase(symbol)) - throw AutomatonException("Stack symbol \"" + symbol.getSymbol() + "\" doesn't exist."); +bool UnknownAutomaton::removeInitialSymbol(const alphabet::Symbol& symbol) { + return stackAlphabet.erase(symbol); } const std::set<alphabet::Symbol>& UnknownAutomaton::getInitialSymbols() const { @@ -86,24 +118,19 @@ const std::set<alphabet::Symbol>& UnknownAutomaton::getInitialSymbols() const { } -void UnknownAutomaton::addTapeSymbol(const alphabet::Symbol& symbol) { - if (!tapeAlphabet.insert(symbol).second) { - throw AutomatonException("Tape symbol \"" + symbol.getSymbol() + "\" already exists."); - } +bool UnknownAutomaton::addTapeSymbol(const alphabet::Symbol& symbol) { + return tapeAlphabet.insert(symbol).second; } -void UnknownAutomaton::setTapeAlphabet(const std::set<alphabet::Symbol>& symbols) { +void UnknownAutomaton::setTapeSymbols(const std::set<alphabet::Symbol>& symbols) { tapeAlphabet = symbols; } -void UnknownAutomaton::removeTapeSymbol(const alphabet::Symbol& symbol) { - int removed = tapeAlphabet.erase(symbol); - if (!removed) { - throw AutomatonException("Tape symbol \"" + symbol.getSymbol() + "\" doesn't exist."); - } +bool UnknownAutomaton::removeTapeSymbol(const alphabet::Symbol& symbol) { + return tapeAlphabet.erase(symbol); } -const std::set<alphabet::Symbol>& UnknownAutomaton::getTapeAlphabet() const { +const std::set<alphabet::Symbol>& UnknownAutomaton::getTapeSymbols() const { return tapeAlphabet; } @@ -127,16 +154,12 @@ const alphabet::Symbol& UnknownAutomaton::getBlankSymbol() const { } -void UnknownAutomaton::addTransition(const UnknownTransition& transition) { - if (!transitions.insert(transition).second) { - throw AutomatonException("Transition already exists."); - } +bool UnknownAutomaton::addTransition(const UnknownTransition& transition) { + return transitions.insert(transition).second; } -void UnknownAutomaton::removeTransition(const UnknownTransition& transition) { - if (!transitions.erase(transition)) { - throw AutomatonException("Transition doesn't exist."); - } +bool UnknownAutomaton::removeTransition(const UnknownTransition& transition) { + return transitions.erase(transition); } const std::set<UnknownTransition>& UnknownAutomaton::getTransitions() const { diff --git a/alib2/src/automaton/UnknownAutomaton.h b/alib2/src/automaton/UnknownAutomaton.h index 1afcd4691fb991e58056819406548ad0e1c3029e..796c844eaac725634bbf48987932b1a3bb8f25f1 100644 --- a/alib2/src/automaton/UnknownAutomaton.h +++ b/alib2/src/automaton/UnknownAutomaton.h @@ -11,7 +11,6 @@ #include <set> #include <list> -#include "Automaton.h" #include "State.h" #include "../alphabet/Symbol.h" #include "UnknownTransition.h" @@ -21,8 +20,12 @@ namespace automaton { /** * Class representing unknown automaton parsed from XML. */ -class UnknownAutomaton: public Automaton { +class UnknownAutomaton { protected: + std::set<State> states; + std::set<State> initialStates; + std::set<State> finalStates; + std::set<alphabet::Symbol> inputAlphabet; std::set<alphabet::Symbol> stackAlphabet; std::set<alphabet::Symbol> initialSymbols; std::set<alphabet::Symbol> tapeAlphabet; @@ -31,7 +34,14 @@ protected: std::set<UnknownTransition> transitions; public: UnknownAutomaton(); - virtual ~UnknownAutomaton(); + ~UnknownAutomaton() noexcept; + + /** + * Adds new state to the automaton. + * @param state State to add + * @throws AutomatonException when state already exist in the automaton + */ + bool addState(const State& state); /** * Set new states of the automaton. @@ -44,7 +54,54 @@ public: * @param state State to remove * @throws AutomatonException when state is not present in the automaton */ - void removeState(const State& state); + bool removeState(const State& state); + + /** + * @return list of states + */ + const std::set<State>& getStates() const; + + + /** + * Adds the State to the initial states. + * @param state State to add + * @throws AutomatonException when state is not present + * in the automaton or when it's already initial state + */ + bool addInitialState(const State& state); + + /** + * Removes the state from the initial states. + * @param state State to remove + * @throws AutomatonException when State is not initial state + */ + bool removeInitialState(const State& state); + + /** + * @return initial states + */ + const std::set<State>& getInitialStates() const; + + + /** + * Adds the State to the final states. + * @param state State to add + * @throws AutomatonException when state is not present + * in the automaton or when it's already final state + */ + bool addFinalState(const State& state); + + /** + * Removes the state from the final states. + * @param state State to remove + * @throws AutomatonException when State is not final state + */ + bool removeFinalState(const State& state); + + /** + * @return final states + */ + const std::set<State>& getFinalStates() const; /** @@ -52,7 +109,12 @@ public: * @param symbol Symbol to add * @throws AutomatonException when symbol is already present in the automaton */ - void addInputSymbol(const alphabet::Symbol& symbol); + bool addInputSymbol(const alphabet::Symbol& symbol); + + /** + * @return the input alphabet + */ + const std::set<alphabet::Symbol>& getInputSymbols() const; /** * Sets the input symbols of the automaton. @@ -65,7 +127,7 @@ public: * @param symbol Symbol to remove * @throws AutomatonException when symbol is not present in input alphabet */ - void removeInputSymbol(const alphabet::Symbol& symbol); + bool removeInputSymbol(const alphabet::Symbol& symbol); /** @@ -73,7 +135,7 @@ public: * @param symbol Symbol to add * @throw AutomatonException when Symbol is already present in stack alphabet */ - void addStackSymbol(const alphabet::Symbol& symbol); + bool addStackSymbol(const alphabet::Symbol& symbol); /** * Sets symbols of the stack alphabet. @@ -86,12 +148,12 @@ public: * @param symbol Symbol to remove * @throw AutomatonException when Symbol is not present in input alphabet */ - void removeStackSymbol(const alphabet::Symbol& symbol); + bool removeStackSymbol(const alphabet::Symbol& symbol); /** * @return the stack alphabet */ - const std::set<alphabet::Symbol>& getStackAlphabet() const; + const std::set<alphabet::Symbol>& getStackSymbols() const; /** @@ -99,7 +161,7 @@ public: * @param symbol Symbol to add * @throw AutomatonException when Symbol is already present in the set of initial symbols */ - void addInitialSymbol(const alphabet::Symbol& symbol); + bool addInitialSymbol(const alphabet::Symbol& symbol); /** * Set the initial symbol list. @@ -112,7 +174,7 @@ public: * @param symbol Symbol to remove * @throw AutomatonException when Symbol is not present in the set of initial symbols */ - void removeInitialSymbol(const alphabet::Symbol& symbol); + bool removeInitialSymbol(const alphabet::Symbol& symbol); /** * @return list of initial symbols @@ -125,25 +187,25 @@ public: * @param symbol Symbol to add * @throw AutomatonException when Symbol is already present in tape alphabet */ - void addTapeSymbol(const alphabet::Symbol& symbol); + bool addTapeSymbol(const alphabet::Symbol& symbol); /** * Sets the tape alphabet. * @param symbols Symbols to become new tape alphabet */ - void setTapeAlphabet(const std::set<alphabet::Symbol>& symbols); + void setTapeSymbols(const std::set<alphabet::Symbol>& symbols); /** * Removes symbol from the tape alphabet. * @param symbol Symbol to remove * @throw AutomatonException when Symbol is not present in tape alphabet */ - void removeTapeSymbol(const alphabet::Symbol& symbol); + bool removeTapeSymbol(const alphabet::Symbol& symbol); /** * @return the tape alphabet */ - const std::set<alphabet::Symbol>& getTapeAlphabet() const; + const std::set<alphabet::Symbol>& getTapeSymbols() const; /** @@ -174,14 +236,14 @@ public: * @param transition UnknownTransition to add * @throws AutomatonException when transition is already present in the automaton */ - void addTransition(const UnknownTransition& transition); + bool addTransition(const UnknownTransition& transition); /** * Removes the transition from the automaton. * @param transition UnknownTransition to remove * @throws AutomatonException when transition is not present in the automaton */ - void removeTransition(const UnknownTransition& transition); + bool removeTransition(const UnknownTransition& transition); /** * @return transitions of the automaton @@ -200,3 +262,4 @@ public: } /* namespace automaton */ #endif /* UNKNOWN_AUTOMATON_H_ */ + diff --git a/alib2/src/factory/AutomatonConvertor.cpp b/alib2/src/factory/AutomatonConvertor.cpp index c35a1ac1ebea28cd825130c94949dedf73dadac9..72e88f347cad4c7a286289491076c916a25f6f51 100644 --- a/alib2/src/factory/AutomatonConvertor.cpp +++ b/alib2/src/factory/AutomatonConvertor.cpp @@ -26,42 +26,9 @@ Automaton* AutomatonConvertor::buildAutomaton(const UnknownAutomaton& automaton) } } -void AutomatonConvertor::buildCommon(Automaton& automaton,const UnknownAutomaton& unknownAutomaton) { - std::set<State>::const_iterator state; - std::set<alphabet::Symbol>::const_iterator symbol; - - const std::set<State>& states = unknownAutomaton.getStates(); - state = states.begin(); - while (state != states.end()) { - automaton.addState(*state); - state++; - } - - const std::set<alphabet::Symbol>& inputAlphabet = unknownAutomaton.getInputAlphabet(); - symbol = inputAlphabet.begin(); - while (symbol != inputAlphabet.end()) { - automaton.addInputSymbol(*symbol); - symbol++; - } - - const std::set<State>& initialStates = unknownAutomaton.getInitialStates(); - state = initialStates.begin(); - while (state != initialStates.end()) { - automaton.addInitialState(*state); - state++; - } - - const std::set<State>& finalStates = unknownAutomaton.getFinalStates(); - state = finalStates.begin(); - while (state != finalStates.end()) { - automaton.addFinalState(*state); - state++; - } -} - bool AutomatonConvertor::isEpsilonNFA(const UnknownAutomaton& automaton) { - if (automaton.getStackAlphabet().size() > 0 || automaton.getInitialSymbols().size() > 0 - || automaton.getTapeAlphabet().size() > 0 || automaton.hasBlankSymbol()) { + if (automaton.getStackSymbols().size() > 0 || automaton.getInitialSymbols().size() > 0 + || automaton.getTapeSymbols().size() > 0 || automaton.hasBlankSymbol()) { return false; } @@ -85,7 +52,10 @@ bool AutomatonConvertor::isEpsilonNFATransition(const UnknownTransition& transit EpsilonNFA AutomatonConvertor::buildEpsilonNFA(const UnknownAutomaton& automaton) { EpsilonNFA fsm; - buildCommon(fsm, automaton); + fsm.setStates(automaton.getStates()); + fsm.setInputSymbols(automaton.getInputSymbols()); + fsm.setInitialStates(automaton.getInitialStates()); + fsm.setFinalStates(automaton.getFinalStates()); const std::set<UnknownTransition> transitions = automaton.getTransitions(); std::set<UnknownTransition>::const_iterator transition = transitions.begin(); @@ -98,7 +68,7 @@ EpsilonNFA AutomatonConvertor::buildEpsilonNFA(const UnknownAutomaton& automaton } bool AutomatonConvertor::isPDA(const UnknownAutomaton& automaton) { - if (automaton.getTapeAlphabet().size() > 0 || automaton.hasBlankSymbol()) { + if (automaton.getTapeSymbols().size() > 0 || automaton.hasBlankSymbol()) { return false; } @@ -120,15 +90,11 @@ bool AutomatonConvertor::isPDATransition(const UnknownTransition& transition) { PDA AutomatonConvertor::buildPDA(const UnknownAutomaton& automaton) { PDA pda; - buildCommon(pda, automaton); - - const std::set<alphabet::Symbol>& stackAlphabet = automaton.getStackAlphabet(); - std::set<alphabet::Symbol>::iterator stackSymbol = stackAlphabet.begin(); - while (stackSymbol != stackAlphabet.end()) { - pda.addStackSymbol(*stackSymbol); - stackSymbol++; - } - + pda.setStates(automaton.getStates()); + pda.setInputSymbols(automaton.getInputSymbols()); + pda.setInitialStates(automaton.getInitialStates()); + pda.setFinalStates(automaton.getFinalStates()); + pda.setStackSymbols(automaton.getStackSymbols()); pda.setInitialSymbols(automaton.getInitialSymbols()); const std::set<UnknownTransition>& transitions = automaton.getTransitions(); @@ -142,7 +108,11 @@ PDA AutomatonConvertor::buildPDA(const UnknownAutomaton& automaton) { } bool AutomatonConvertor::isOneTapeDTM(const UnknownAutomaton& automaton) { - if (automaton.getStackAlphabet().size() > 0 || automaton.getInitialSymbols().size() > 0) { + if(!automaton.hasBlankSymbol()) return false; + + if(automaton.getInitialStates().size() > 1) return false; + + if (automaton.getStackSymbols().size() > 0 || automaton.getInitialSymbols().size() > 0) { return false; } @@ -165,18 +135,12 @@ bool AutomatonConvertor::isOneTapeDTMTransition(const UnknownTransition& transit } OneTapeDTM AutomatonConvertor::buildOneTapeDTM(const UnknownAutomaton& automaton) { - OneTapeDTM tm; - - const std::set<alphabet::Symbol>& tapeAlphabet = automaton.getTapeAlphabet(); - std::set<alphabet::Symbol>::const_iterator tapeSymbol = tapeAlphabet.begin(); - while (tapeSymbol != tapeAlphabet.end()) { - tm.addTapeSymbol(*tapeSymbol); - tapeSymbol++; - } - - buildCommon(tm, automaton); - - tm.setBlankSymbol(automaton.getBlankSymbol()); + OneTapeDTM tm(*automaton.getInitialStates().begin(), automaton.getBlankSymbol()); + + tm.setTapeSymbols(automaton.getTapeSymbols()); + tm.setStates(automaton.getStates()); + tm.setInputSymbols(automaton.getInputSymbols()); + tm.setFinalStates(automaton.getFinalStates()); const std::set<UnknownTransition>& transitions = automaton.getTransitions(); std::set<UnknownTransition>::const_iterator transition = transitions.begin(); diff --git a/alib2/test-src/automaton/AutomatonTest.cpp b/alib2/test-src/automaton/AutomatonTest.cpp index 4670477bf3a4508590f48ffb14b66d6259715306..5731264a5c9b689002af151471d1462f37aeed42 100644 --- a/alib2/test-src/automaton/AutomatonTest.cpp +++ b/alib2/test-src/automaton/AutomatonTest.cpp @@ -8,6 +8,10 @@ #include "automaton/AutomatonFromXMLParser.h" #include "automaton/AutomatonToXMLComposer.h" +#include "automaton/FSM/DFA.h" +#include "automaton/FSM/FSMFromXMLParser.h" +#include "automaton/FSM/FSMToXMLComposer.h" + #include "factory/AutomatonFactory.h" #define CPPUNIT_IMPLY(x, y) CPPUNIT_ASSERT(!(x) || (y)) @@ -49,3 +53,33 @@ void AutomatonTest::testXMLParser() { } } +void AutomatonTest::testDFAParser() { + automaton::DFA automaton(automaton::State("1")); + + automaton.addState(automaton::State("1")); + automaton.addState(automaton::State("2")); + automaton.addState(automaton::State("3")); + automaton.addInputSymbol(alphabet::Symbol("a")); + automaton.addInputSymbol(alphabet::Symbol("b")); + + automaton.addTransition(automaton::State("1"), alphabet::Symbol("a"), automaton::State("2")); + automaton.addTransition(automaton::State("2"), alphabet::Symbol("b"), automaton::State("1")); + + automaton.addFinalState(automaton::State("3")); + + CPPUNIT_ASSERT( automaton == automaton ); + { + automaton::FSMToXMLComposer composer; + std::list<sax::Token> tokens = composer.compose(automaton); + std::string tmp; + sax::SaxComposeInterface::printMemory(tmp, tokens); + + std::list<sax::Token> tokens2; + sax::SaxParseInterface::parseMemory(tmp, tokens2); + automaton::FSMFromXMLParser parser; + automaton::DFA automaton2 = parser.parseDFA(tokens2); + + CPPUNIT_ASSERT( automaton == automaton2 ); + } +} + diff --git a/alib2/test-src/automaton/AutomatonTest.h b/alib2/test-src/automaton/AutomatonTest.h index ceb0b00f2e5d6682f5d6be7756d219573b68bd81..261c2901bbf35c5b13738fa223e7c6663deca523 100644 --- a/alib2/test-src/automaton/AutomatonTest.h +++ b/alib2/test-src/automaton/AutomatonTest.h @@ -7,6 +7,7 @@ class AutomatonTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE( AutomatonTest ); CPPUNIT_TEST( testXMLParser ); + CPPUNIT_TEST( testDFAParser ); CPPUNIT_TEST_SUITE_END(); public: @@ -14,6 +15,7 @@ public: void tearDown(); void testXMLParser(); + void testDFAParser(); }; #endif // AUTOMATON_TEST_H_