From 27e4b72fd5e1fb4bff6eecf27fba77558491532c Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Sun, 29 May 2016 22:52:13 +0200 Subject: [PATCH] Tree automata use components --- .../exact/ExactPatternMatchingAutomaton.cpp | 2 +- .../exact/ExactSubtreeMatchingAutomaton.cpp | 2 +- .../determinize/DeterminizeNFTAPart.cxx | 2 +- .../automaton/determinize/determinizeTest.cpp | 2 +- alib2data/src/automaton/TA/DFTA.cpp | 135 ++++++++++++------ alib2data/src/automaton/TA/DFTA.h | 78 +++++++--- alib2data/src/automaton/TA/NFTA.cpp | 128 +++++++++++------ alib2data/src/automaton/TA/NFTA.h | 78 +++++++--- .../test-src/automaton/AutomatonTest.cpp | 8 +- 9 files changed, 295 insertions(+), 140 deletions(-) diff --git a/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.cpp b/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.cpp index a0cb96c0bb..e79c62ad0d 100644 --- a/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.cpp +++ b/alib2algo/src/arbology/exact/ExactPatternMatchingAutomaton.cpp @@ -232,7 +232,7 @@ automaton::NFTA ExactPatternMatchingAutomaton::construct ( const tree::RankedPat alphabet.erase ( pattern.getSubtreeWildcard ( ) ); automaton::NFTA res; - res.setInputSymbols ( alphabet ); + res.setInputAlphabet ( alphabet ); int nextState = 0; diff --git a/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.cpp b/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.cpp index 432f1c1638..6a3cd905d2 100644 --- a/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.cpp +++ b/alib2algo/src/arbology/exact/ExactSubtreeMatchingAutomaton.cpp @@ -100,7 +100,7 @@ automaton::State constructRecursive ( const tree::RankedNode & node, automaton:: automaton::NFTA ExactSubtreeMatchingAutomaton::construct ( const tree::RankedTree & pattern ) { automaton::NFTA res; - res.setInputSymbols ( pattern.getAlphabet ( ) ); + res.setInputAlphabet ( pattern.getAlphabet ( ) ); int nextState = 0; res.addFinalState ( constructRecursive ( pattern.getRoot ( ), res, nextState ) ); return res; diff --git a/alib2algo/src/automaton/determinize/DeterminizeNFTAPart.cxx b/alib2algo/src/automaton/determinize/DeterminizeNFTAPart.cxx index a76a5e00c4..fbc5d2557c 100644 --- a/alib2algo/src/automaton/determinize/DeterminizeNFTAPart.cxx +++ b/alib2algo/src/automaton/determinize/DeterminizeNFTAPart.cxx @@ -31,7 +31,7 @@ std::set<State> getTransitionRightSide(const NFTA & nfta, const alphabet::Ranked DFTA Determinize::determinize(const NFTA & nfta) { DFTA res; - res.setInputSymbols(nfta.getInputAlphabet()); + res.setInputAlphabet(nfta.getInputAlphabet()); for (const auto & state : nfta.getStates()) res.addState(createDFAState({state})); for (const auto & state : nfta.getFinalStates()) res.addFinalState(createDFAState({state})); diff --git a/alib2algo/test-src/automaton/determinize/determinizeTest.cpp b/alib2algo/test-src/automaton/determinize/determinizeTest.cpp index 500099a10c..f3bb704b9f 100644 --- a/alib2algo/test-src/automaton/determinize/determinizeTest.cpp +++ b/alib2algo/test-src/automaton/determinize/determinizeTest.cpp @@ -113,7 +113,7 @@ void determinizeTest::testDeterminizeNFTA() { const alphabet::RankedSymbol b ('b', 1); const alphabet::RankedSymbol c ('c', 0); const std::set<alphabet::RankedSymbol> alphabet {a, b, c}; - automaton.setInputSymbols(alphabet); + automaton.setInputAlphabet(alphabet); automaton.addState(automaton::State(1)); automaton.addState(automaton::State(2)); diff --git a/alib2data/src/automaton/TA/DFTA.cpp b/alib2data/src/automaton/TA/DFTA.cpp index 91029cc875..911d8edfae 100644 --- a/alib2data/src/automaton/TA/DFTA.cpp +++ b/alib2data/src/automaton/TA/DFTA.cpp @@ -19,8 +19,10 @@ namespace automaton { -DFTA::DFTA() { +DFTA::DFTA ( std::set < State > states, std::set < alphabet::RankedSymbol > inputAlphabet, std::set < State > finalStates ) : std::Components < DFTA, alphabet::RankedSymbol, std::tuple < InputAlphabet >, std::tuple < >, automaton::State, std::tuple < States, FinalStates >, std::tuple < > > ( std::make_tuple ( std::move ( inputAlphabet ) ), std::tuple < > ( ), std::make_tuple ( std::move ( states ), std::move ( finalStates ) ), std::tuple < > ( ) ) { +} +DFTA::DFTA() : DFTA ( std::set < State > { }, std::set < alphabet::RankedSymbol > { }, std::set < State > { } ) { } AutomatonBase* DFTA::clone() const { @@ -31,52 +33,27 @@ AutomatonBase* DFTA::plunder() && { return new DFTA(std::move(*this)); } -bool DFTA::removeState(const State& state) { - if (finalStates.find(state) != finalStates.end()) { - throw AutomatonException("State \"" + (std::string) state.getName() + "\" is final state."); - } - - AutomatonException ex ("State \"" + (std::string) state.getName() + "\" is used in transition."); - for (const std::pair<const std::pair<alphabet::RankedSymbol, std::vector<State> >, State>& t : transitions) { - const std::vector<State>& states = t . first.second; - for (const State& it : states) { - if (it == state) throw ex; - } - if (t . second == state) throw ex; - } - - return states.erase(state); -} - -bool DFTA::removeInputSymbol(const alphabet::RankedSymbol& symbol) { - for (const std::pair<const std::pair<alphabet::RankedSymbol, std::vector<State> >, State>& t : transitions) { - if (t . first.first == symbol) - throw AutomatonException("Input symbol \"" + (std::string) symbol + "\" is used."); - } - - return inputAlphabet.erase(symbol); -} - bool DFTA::addTransition(const alphabet::RankedSymbol & symbol, const std::vector<State> & prevStates, const State & next) { - if (prevStates.size() != symbol.getRank().getData()) + if ( prevStates.size() != symbol.getRank().getData()) throw AutomatonException("Number of states doesn't match rank of the symbol"); - if (inputAlphabet.find(symbol) == inputAlphabet.end()) + if (! getInputAlphabet().count(symbol)) throw AutomatonException("Input symbol \"" + (std::string) symbol + "\" doesn't exist."); - if (states.find(next) == states.end()) + if (! getStates().count(next)) throw AutomatonException("State \"" + (std::string) next.getName() + "\" doesn't exist."); for (const State& it : prevStates) { - if (states.find(it) == states.end()) + if (! getStates().count(it)) throw AutomatonException("State \"" + (std::string) it . getName() + "\" doesn't exist."); } std::pair<alphabet::RankedSymbol, std::vector<State> > key = std::make_pair(symbol, prevStates); - const auto & it = transitions.find(key); - if (it != transitions.end()) { - if (it -> second == next) return false; - else throw AutomatonException("Transition already exists"); + if ( transitions.find ( key ) != transitions.end ( ) ) { + if ( transitions.find ( key )->second == next ) + return false; + else + throw AutomatonException("Transition already exists"); } transitions.insert(std::make_pair(key, next)); @@ -85,15 +62,20 @@ bool DFTA::addTransition(const alphabet::RankedSymbol & symbol, const std::vecto bool DFTA::removeTransition(const alphabet::RankedSymbol symbol, const std::vector<State> & states, const State & next) { std::pair<alphabet::RankedSymbol, std::vector<State> > key = std::make_pair(symbol, states); - const auto & it = transitions.find(key); - if (it == transitions.end()) return false; - if (it -> second != next) throw AutomatonException("Transition does not exist"); - return transitions.erase(key); + + if ( transitions.find ( key ) == transitions.end ( ) ) + return false; + + if ( transitions.find ( key )->second != next ) + throw AutomatonException("Transition does not exist"); + + transitions.erase(key); + return true; } int DFTA::compare(const DFTA& other) const { - auto first = std::tie(states, inputAlphabet, finalStates, transitions); - auto second = std::tie(other.states, other.inputAlphabet, other.finalStates, other.transitions); + auto first = std::tie(getStates(), getInputAlphabet(), getFinalStates(), transitions); + auto second = std::tie(other.getStates(), other.getInputAlphabet(), other.getFinalStates(), other.transitions); std::compare<decltype(first)> comp; return comp(first, second); @@ -101,9 +83,9 @@ int DFTA::compare(const DFTA& other) const { void DFTA::operator>>(std::ostream& out) const { out << "(DFTA " - << " states = " << states - << " inputAlphabet = " << inputAlphabet - << " finalStates = " << finalStates + << " states = " << getStates() + << " inputAlphabet = " << getInputAlphabet() + << " finalStates = " << getFinalStates() << " transitions = " << transitions << ")"; } @@ -125,7 +107,7 @@ DFTA DFTA::parse(std::deque<sax::Token>::iterator& input) { DFTA automaton; automaton.setStates(std::move(states)); - automaton.setInputSymbols(std::move(inputSymbols)); + automaton.setInputAlphabet(std::move(inputSymbols)); automaton.setFinalStates(std::move(finalStates)); AutomatonFromXMLParser::parseTransitions<DFTA>(input, automaton); @@ -172,6 +154,69 @@ void DFTA::composeTransitions(std::deque<sax::Token>& out) const { } /* namespace automaton */ +namespace std { + +template < > +bool automaton::DFTA::Component < automaton::DFTA, alphabet::RankedSymbol, automaton::InputAlphabet >::used ( const alphabet::RankedSymbol & symbol ) const { + const automaton::DFTA * automaton = static_cast < const automaton::DFTA * > ( this ); + + for (const std::pair<const std::pair<alphabet::RankedSymbol, std::vector<automaton::State> >, automaton::State>& t : automaton->getTransitions()) + if (t.first.first == symbol) + return true; + + return false; +} + +template < > +bool automaton::DFTA::Component < automaton::DFTA, alphabet::RankedSymbol, automaton::InputAlphabet >::available ( const alphabet::RankedSymbol & ) const { + return true; +} + +template < > +void automaton::DFTA::Component < automaton::DFTA, alphabet::RankedSymbol, automaton::InputAlphabet >::valid ( const alphabet::RankedSymbol & ) const { +} + +template < > +bool automaton::DFTA::Component < automaton::DFTA, automaton::State, automaton::States >::used ( const automaton::State & state ) const { + const automaton::DFTA * automaton = static_cast < const automaton::DFTA * > ( this ); + + if ( automaton->getFinalStates ( ).count ( state ) ) + return true; + + for (const std::pair<const std::pair<alphabet::RankedSymbol, std::vector<automaton::State> >, automaton::State>& t : automaton->getTransitions()) + if(std::contains(t.first.second.begin(), t.first.second.end(), state ) || t.second == state) + return true; + + return false; +} + +template < > +bool automaton::DFTA::Component < automaton::DFTA, automaton::State, automaton::States >::available ( const automaton::State & ) const { + return true; +} + +template < > +void automaton::DFTA::Component < automaton::DFTA, automaton::State, automaton::States >::valid ( const automaton::State & ) const { +} + +template < > +bool automaton::DFTA::Component < automaton::DFTA, automaton::State, automaton::FinalStates >::used ( const automaton::State & ) const { + return false; +} + +template < > +bool automaton::DFTA::Component < automaton::DFTA, automaton::State, automaton::FinalStates >::available ( const automaton::State & state ) const { + const automaton::DFTA * automaton = static_cast < const automaton::DFTA * > ( this ); + + return automaton->accessComponent < automaton::States > ( ).get ( ).count ( state ); +} + +template < > +void automaton::DFTA::Component < automaton::DFTA, automaton::State, automaton::FinalStates >::valid ( const automaton::State & ) const { +} + +} /* namespace std */ + namespace alib { auto DFTAParserRegister = xmlApi<automaton::Automaton>::ParserRegister<automaton::DFTA>(); diff --git a/alib2data/src/automaton/TA/DFTA.h b/alib2data/src/automaton/TA/DFTA.h index 127e2d6796..f715de18cf 100644 --- a/alib2data/src/automaton/TA/DFTA.h +++ b/alib2data/src/automaton/TA/DFTA.h @@ -10,39 +10,83 @@ #include <map> #include <vector> +#include <core/components.hpp> #include "../AutomatonBase.h" -#include "../common/States.h" - -// #include "../common/InputAlphabet.h" +#include "../common/State.h" #include "../../alphabet/RankedSymbol.h" namespace automaton { +class InputAlphabet; +class States; +class FinalStates; + /** * Represents Finite Tree Automaton. * Can store nondeterministic finite automaton without epsilon transitions. */ -class DFTA : public AutomatonBase, public States { -protected: - std::set < alphabet::RankedSymbol > inputAlphabet; +class DFTA : public AutomatonBase, public std::Components < DFTA, alphabet::RankedSymbol, std::tuple < InputAlphabet >, std::tuple < >, automaton::State, std::tuple < States, FinalStates >, std::tuple < > > { std::map < std::pair < alphabet::RankedSymbol, std::vector < State > >, State > transitions; public: explicit DFTA ( ); + explicit DFTA ( std::set < State > states, std::set < alphabet::RankedSymbol > inputAlphabet, std::set < State > finalStates ); virtual AutomatonBase * clone ( ) const; virtual AutomatonBase * plunder ( ) &&; - /** - * @copydoc Automaton::removeState(const State&) - */ - virtual bool removeState ( const State & state ); + const std::set < State > & getStates ( ) const { + return accessComponent < States > ( ).get ( ); + } - /** - * @copydoc Automaton::removeInputSymbol(const Symbol&) - */ - virtual bool removeInputSymbol ( const alphabet::RankedSymbol & symbol ); + bool addState ( State state ) { + return accessComponent < States > ( ).add ( std::move ( state ) ); + } + + void setStates ( std::set < State > states ) { + accessComponent < States > ( ).set ( std::move ( states ) ); + } + + void removeState ( const State & state ) { + accessComponent < States > ( ).remove ( state ); + } + + const std::set < State > & getFinalStates ( ) const { + return accessComponent < FinalStates > ( ).get ( ); + } + + bool addFinalState ( State state ) { + return accessComponent < FinalStates > ( ).add ( std::move ( state ) ); + } + + void setFinalStates ( std::set < State > states ) { + accessComponent < FinalStates > ( ).set ( std::move ( states ) ); + } + + void removeFinalState ( const State & state ) { + accessComponent < FinalStates > ( ).remove ( state ); + } + + const std::set < alphabet::RankedSymbol > & getInputAlphabet ( ) const { + return accessComponent < InputAlphabet > ( ).get ( ); + } + + bool addInputSymbol ( alphabet::RankedSymbol symbol ) { + return accessComponent < InputAlphabet > ( ).add ( std::move ( symbol ) ); + } + + void addInputSymbols ( std::set < alphabet::RankedSymbol > symbols ) { + accessComponent < InputAlphabet > ( ).add ( std::move ( symbols ) ); + } + + void setInputAlphabet ( std::set < alphabet::RankedSymbol > symbols ) { + accessComponent < InputAlphabet > ( ).set ( std::move ( symbols ) ); + } + + void removeInputSymbol ( const alphabet::RankedSymbol & symbol ) { + accessComponent < InputAlphabet > ( ).remove ( symbol ); + } /** * Adds transition defined by parameters to the automaton. @@ -68,12 +112,6 @@ public: unsigned transitionsSize ( ) const; - const std::set < alphabet::RankedSymbol > & getInputAlphabet ( ) const { return inputAlphabet; } - - void setInputSymbols ( const std::set < alphabet::RankedSymbol > & symbols ) { inputAlphabet = symbols; } - - void addInputSymbol ( const alphabet::RankedSymbol & symbol ) { inputAlphabet.insert ( symbol ); } - virtual int compare ( const ObjectBase & other ) const { if ( std::type_index ( typeid ( * this ) ) == std::type_index ( typeid ( other ) ) ) return this->compare ( ( decltype ( * this ) )other ); diff --git a/alib2data/src/automaton/TA/NFTA.cpp b/alib2data/src/automaton/TA/NFTA.cpp index 6bc2a57280..93a6989ee8 100644 --- a/alib2data/src/automaton/TA/NFTA.cpp +++ b/alib2data/src/automaton/TA/NFTA.cpp @@ -19,14 +19,13 @@ namespace automaton { -NFTA::NFTA() { +NFTA::NFTA ( std::set < State > states, std::set < alphabet::RankedSymbol > inputAlphabet, std::set < State > finalStates ) : std::Components < NFTA, alphabet::RankedSymbol, std::tuple < InputAlphabet >, std::tuple < >, automaton::State, std::tuple < States, FinalStates >, std::tuple < > > ( std::make_tuple ( std::move ( inputAlphabet ) ), std::tuple < > ( ), std::make_tuple ( std::move ( states ), std::move ( finalStates ) ), std::tuple < > ( ) ) { +} +NFTA::NFTA() : NFTA ( std::set < State > { }, std::set < alphabet::RankedSymbol > { }, std::set < State > { } ) { } -NFTA::NFTA(const DFTA& other) { - inputAlphabet = other.getInputAlphabet(); - states = other.getStates(); - finalStates = other.getFinalStates(); +NFTA::NFTA(const DFTA& other) : NFTA ( other.getStates(), other.getInputAlphabet(), other.getFinalStates() ) { for(const auto& transition : other.getTransitions()) { transitions[transition.first].insert(transition.second); } @@ -40,45 +39,18 @@ AutomatonBase* NFTA::plunder() && { return new NFTA(std::move(*this)); } -bool NFTA::removeState(const State& state) { - if (finalStates.find(state) != finalStates.end()) { - throw AutomatonException("State \"" + (std::string) state.getName() + "\" is final state."); - } - - AutomatonException ex ("State \"" + (std::string) state.getName() + "\" is used in transition."); - for (const std::pair<const std::pair<alphabet::RankedSymbol, std::vector<State> >, std::set<State> >& t : transitions) { - const std::vector<State>& states = t . first.second; - for (const State& it : states) { - if (it == state) throw ex; - } - if (t . second.find(state) != t . second.end()) throw ex; - } - - return states.erase(state); -} - -bool NFTA::removeInputSymbol(const alphabet::RankedSymbol& symbol) { - for (const std::pair<const std::pair<alphabet::RankedSymbol, std::vector<State> >, std::set<State> >& t : transitions) { - if (t . first.first == symbol) - throw AutomatonException("Input symbol \"" + (std::string) symbol + "\" is used."); - } - - return inputAlphabet.erase(symbol); -} - bool NFTA::addTransition(const alphabet::RankedSymbol & symbol, const std::vector<State> & prevStates, const State & next) { - if (prevStates.size() != symbol.getRank().getData()) throw AutomatonException("Number of states doesn't match rank of the symbol"); - if (inputAlphabet.find(symbol) == inputAlphabet.end()) + if (! getInputAlphabet().count(symbol)) throw AutomatonException("Input symbol \"" + (std::string) symbol + "\" doesn't exist."); - if (states.find(next) == states.end()) + if (! getStates().count(next)) throw AutomatonException("State \"" + (std::string) next.getName() + "\" doesn't exist."); for (const State& it : prevStates) { - if (states.find(it) == states.end()) + if (! getStates().count(it)) throw AutomatonException("State \"" + (std::string) it . getName() + "\" doesn't exist."); } @@ -92,26 +64,25 @@ bool NFTA::removeTransition(const alphabet::RankedSymbol symbol, const std::vect } bool NFTA::isDeterministic() const { - for (const std::pair<const std::pair<alphabet::RankedSymbol, std::vector<State> >, std::set<State> >& t : transitions) { - if (t . second.size() != 1 || t . second.size() != 0) { + for (const std::pair<const std::pair<alphabet::RankedSymbol, std::vector<State> >, std::set<State> >& t : transitions) + if (t . second.size() != 1 || t . second.size() != 0) return false; - } - } return true; } unsigned NFTA::transitionsSize() const { int res = 0; - for(const auto& transition : transitions ){ + + for(const auto& transition : transitions ) res += transition.second.size(); - } + return res; } int NFTA::compare(const NFTA& other) const { - auto first = std::tie(states, inputAlphabet, finalStates, transitions); - auto second = std::tie(other.states, other.inputAlphabet, other.finalStates, other.transitions); + auto first = std::tie(getStates(), getInputAlphabet(), getFinalStates(), transitions); + auto second = std::tie(other.getStates(), other.getInputAlphabet(), other.getFinalStates(), other.transitions); std::compare<decltype(first)> comp; return comp(first, second); @@ -119,9 +90,9 @@ int NFTA::compare(const NFTA& other) const { void NFTA::operator>>(std::ostream& out) const { out << "(NFTA " - << " states = " << states - << " inputAlphabet = " << inputAlphabet - << " finalStates = " << finalStates + << " states = " << getStates() + << " inputAlphabet = " << getInputAlphabet() + << " finalStates = " << getFinalStates() << " transitions = " << transitions << ")"; } @@ -143,7 +114,7 @@ NFTA NFTA::parse(std::deque<sax::Token>::iterator& input) { NFTA automaton; automaton.setStates(std::move(states)); - automaton.setInputSymbols(std::move(inputSymbols)); + automaton.setInputAlphabet(std::move(inputSymbols)); automaton.setFinalStates(std::move(finalStates)); AutomatonFromXMLParser::parseTransitions<NFTA>(input, automaton); @@ -192,6 +163,69 @@ void NFTA::composeTransitions(std::deque<sax::Token>& out) const { } /* namespace automaton */ +namespace std { + +template < > +bool automaton::NFTA::Component < automaton::NFTA, alphabet::RankedSymbol, automaton::InputAlphabet >::used ( const alphabet::RankedSymbol & symbol ) const { + const automaton::NFTA * automaton = static_cast < const automaton::NFTA * > ( this ); + + for (const std::pair<const std::pair<alphabet::RankedSymbol, std::vector<automaton::State> >, std::set<automaton::State>>& t : automaton->getTransitions()) + if (t.first.first == symbol) + return true; + + return false; +} + +template < > +bool automaton::NFTA::Component < automaton::NFTA, alphabet::RankedSymbol, automaton::InputAlphabet >::available ( const alphabet::RankedSymbol & ) const { + return true; +} + +template < > +void automaton::NFTA::Component < automaton::NFTA, alphabet::RankedSymbol, automaton::InputAlphabet >::valid ( const alphabet::RankedSymbol & ) const { +} + +template < > +bool automaton::NFTA::Component < automaton::NFTA, automaton::State, automaton::States >::used ( const automaton::State & state ) const { + const automaton::NFTA * automaton = static_cast < const automaton::NFTA * > ( this ); + + if ( automaton->getFinalStates ( ).count ( state ) ) + return true; + + for (const std::pair<const std::pair<alphabet::RankedSymbol, std::vector<automaton::State> >, std::set<automaton::State>>& t : automaton->getTransitions()) + if(std::contains(t.first.second.begin(), t.first.second.end(), state ) || t . second.count ( state ) ) + return true; + + return false; +} + +template < > +bool automaton::NFTA::Component < automaton::NFTA, automaton::State, automaton::States >::available ( const automaton::State & ) const { + return true; +} + +template < > +void automaton::NFTA::Component < automaton::NFTA, automaton::State, automaton::States >::valid ( const automaton::State & ) const { +} + +template < > +bool automaton::NFTA::Component < automaton::NFTA, automaton::State, automaton::FinalStates >::used ( const automaton::State & ) const { + return false; +} + +template < > +bool automaton::NFTA::Component < automaton::NFTA, automaton::State, automaton::FinalStates >::available ( const automaton::State & state ) const { + const automaton::NFTA * automaton = static_cast < const automaton::NFTA * > ( this ); + + return automaton->accessComponent < automaton::States > ( ).get ( ).count ( state ); +} + +template < > +void automaton::NFTA::Component < automaton::NFTA, automaton::State, automaton::FinalStates >::valid ( const automaton::State & ) const { +} + +} /* namespace std */ + namespace alib { auto NFTAParserRegister = xmlApi<automaton::Automaton>::ParserRegister<automaton::NFTA>(); diff --git a/alib2data/src/automaton/TA/NFTA.h b/alib2data/src/automaton/TA/NFTA.h index 237dc60f51..e3c906c37a 100644 --- a/alib2data/src/automaton/TA/NFTA.h +++ b/alib2data/src/automaton/TA/NFTA.h @@ -10,42 +10,86 @@ #include <map> #include <vector> +#include <core/components.hpp> #include "../AutomatonBase.h" -#include "../common/States.h" - -// #include "../common/InputAlphabet.h" +#include "../common/State.h" #include "../../alphabet/RankedSymbol.h" #include "DFTA.h" namespace automaton { +class InputAlphabet; +class States; +class FinalStates; + /** * Represents Finite Tree Automaton. * Can store nondeterministic finite tree automaton without epsilon transitions. */ -class NFTA : public AutomatonBase, public States { -protected: - std::set < alphabet::RankedSymbol > inputAlphabet; +class NFTA : public AutomatonBase, public std::Components < NFTA, alphabet::RankedSymbol, std::tuple < InputAlphabet >, std::tuple < >, automaton::State, std::tuple < States, FinalStates >, std::tuple < > > { std::map < std::pair < alphabet::RankedSymbol, std::vector < State > >, std::set < State > > transitions; public: explicit NFTA ( ); + explicit NFTA ( std::set < State > states, std::set < alphabet::RankedSymbol > inputAlphabet, std::set < State > finalStates ); explicit NFTA ( const DFTA & other ); virtual AutomatonBase * clone ( ) const; virtual AutomatonBase * plunder ( ) &&; - /** - * @copydoc Automaton::removeState(const State&) - */ - virtual bool removeState ( const State & state ); + const std::set < State > & getStates ( ) const { + return accessComponent < States > ( ).get ( ); + } - /** - * @copydoc Automaton::removeInputSymbol(const Symbol&) - */ - virtual bool removeInputSymbol ( const alphabet::RankedSymbol & symbol ); + bool addState ( State state ) { + return accessComponent < States > ( ).add ( std::move ( state ) ); + } + + void setStates ( std::set < State > states ) { + accessComponent < States > ( ).set ( std::move ( states ) ); + } + + void removeState ( const State & state ) { + accessComponent < States > ( ).remove ( state ); + } + + const std::set < State > & getFinalStates ( ) const { + return accessComponent < FinalStates > ( ).get ( ); + } + + bool addFinalState ( State state ) { + return accessComponent < FinalStates > ( ).add ( std::move ( state ) ); + } + + void setFinalStates ( std::set < State > states ) { + accessComponent < FinalStates > ( ).set ( std::move ( states ) ); + } + + void removeFinalState ( const State & state ) { + accessComponent < FinalStates > ( ).remove ( state ); + } + + const std::set < alphabet::RankedSymbol > & getInputAlphabet ( ) const { + return accessComponent < InputAlphabet > ( ).get ( ); + } + + bool addInputSymbol ( alphabet::RankedSymbol symbol ) { + return accessComponent < InputAlphabet > ( ).add ( std::move ( symbol ) ); + } + + void addInputSymbols ( std::set < alphabet::RankedSymbol > symbols ) { + accessComponent < InputAlphabet > ( ).add ( std::move ( symbols ) ); + } + + void setInputAlphabet ( std::set < alphabet::RankedSymbol > symbols ) { + accessComponent < InputAlphabet > ( ).set ( std::move ( symbols ) ); + } + + void removeInputSymbol ( const alphabet::RankedSymbol & symbol ) { + accessComponent < InputAlphabet > ( ).remove ( symbol ); + } /** * Adds transition defined by parameters to the automaton. @@ -80,12 +124,6 @@ public: unsigned transitionsSize ( ) const; - const std::set < alphabet::RankedSymbol > & getInputAlphabet ( ) const { return inputAlphabet; } - - void setInputSymbols ( const std::set < alphabet::RankedSymbol > & symbols ) { inputAlphabet = symbols; } - - void addInputSymbol ( const alphabet::RankedSymbol & symbol ) { inputAlphabet.insert ( symbol ); } - virtual int compare ( const ObjectBase & other ) const { if ( std::type_index ( typeid ( * this ) ) == std::type_index ( typeid ( other ) ) ) return this->compare ( ( decltype ( * this ) )other ); diff --git a/alib2data/test-src/automaton/AutomatonTest.cpp b/alib2data/test-src/automaton/AutomatonTest.cpp index d0dc1297a2..2278c9ae97 100644 --- a/alib2data/test-src/automaton/AutomatonTest.cpp +++ b/alib2data/test-src/automaton/AutomatonTest.cpp @@ -309,10 +309,10 @@ void AutomatonTest::testNFTATransitions() { automaton.addFinalState(q2); - CPPUNIT_ASSERT_THROW(automaton.removeInputSymbol(a), automaton::AutomatonException); + CPPUNIT_ASSERT_THROW(automaton.removeInputSymbol(a), exception::CommonException); CPPUNIT_ASSERT_NO_THROW(automaton.removeInputSymbol(d)); CPPUNIT_ASSERT_NO_THROW(automaton.removeTransition(b, states1, q2)); - CPPUNIT_ASSERT_THROW(automaton.addTransition(b, states1, q1), automaton::AutomatonException); - CPPUNIT_ASSERT_THROW(automaton.addTransition(a, states2, q1), automaton::AutomatonException); - CPPUNIT_ASSERT_THROW(automaton.addTransition(d, states3, q0), automaton::AutomatonException); + CPPUNIT_ASSERT_THROW(automaton.addTransition(b, states1, q1), exception::CommonException); + CPPUNIT_ASSERT_THROW(automaton.addTransition(a, states2, q1), exception::CommonException); + CPPUNIT_ASSERT_THROW(automaton.addTransition(d, states3, q0), exception::CommonException); } -- GitLab