diff --git a/alib2data/src/automaton/AutomatonFeatures.h b/alib2data/src/automaton/AutomatonFeatures.h index 97f639307a878becb2ba9bd7a57cf9c23f236ade..0d55baca2869732f402bb5fc5222ea9dca087942 100644 --- a/alib2data/src/automaton/AutomatonFeatures.h +++ b/alib2data/src/automaton/AutomatonFeatures.h @@ -16,6 +16,7 @@ namespace automaton { enum class FEATURES { + MULTI_INITIAL_STATE_EPSILON_NFA, EPSILON_NFA, MULTI_INITIAL_STATE_NFA, NFA, @@ -41,6 +42,8 @@ class Automaton; class AutomatonBase; enum class Shift; +template<class SymbolType = DefaultSymbolType, class EpsilonType = DefaultEpsilonType, class StateType = DefaultStateType > +class MultiInitialStateEpsilonNFA; template<class SymbolType = DefaultSymbolType, class EpsilonType = DefaultEpsilonType, class StateType = DefaultStateType > class EpsilonNFA; template<class SymbolType = DefaultSymbolType, class StateType = DefaultStateType > diff --git a/alib2data/src/automaton/FSM/CompactNFA.cpp b/alib2data/src/automaton/FSM/CompactNFA.cpp index 5c5ef48446db3c242be7e92c78440c3279ccff35..7b9eb5736904ba6e74b34760dac42dba60b3984f 100644 --- a/alib2data/src/automaton/FSM/CompactNFA.cpp +++ b/alib2data/src/automaton/FSM/CompactNFA.cpp @@ -20,6 +20,7 @@ static auto valuePrinter = registration::ValuePrinterRegister < automaton::Compa static auto compactNFAFromDFA = registration::CastRegister < automaton::CompactNFA < >, automaton::DFA < > > ( ); static auto compactNFAFromNFA = registration::CastRegister < automaton::CompactNFA < >, automaton::NFA < > > ( ); static auto compactNFAFromMultiInitialStateNFA = registration::CastRegister < automaton::CompactNFA < >, automaton::MultiInitialStateNFA < > > ( ); -static auto compactNFAEpsilonNFA = registration::CastRegister < automaton::CompactNFA < >, automaton::EpsilonNFA < > > ( ); +static auto compactNFAFromEpsilonNFA = registration::CastRegister < automaton::CompactNFA < >, automaton::EpsilonNFA < > > ( ); +static auto compactNFAFromMultiInitialStateEpsilonNFA = registration::CastRegister < automaton::CompactNFA < >, automaton::MultiInitialStateEpsilonNFA < > > ( ); } /* namespace */ diff --git a/alib2data/src/automaton/FSM/CompactNFA.h b/alib2data/src/automaton/FSM/CompactNFA.h index 42de0344f9c9551588832e6eac07e56f139647a3..a4f1fbf8a92e413d30843c8bb07acff174326800 100644 --- a/alib2data/src/automaton/FSM/CompactNFA.h +++ b/alib2data/src/automaton/FSM/CompactNFA.h @@ -92,6 +92,16 @@ public: */ explicit CompactNFA ( ext::set < StateType > states, ext::set < SymbolType > inputAlphabet, StateType initialState, ext::set < StateType > finalStates ); + /* + * \brief Creates a new instance of the automaton based on the Multi Initial State Epsilon Nondeterministic finite automaton. + * + * \param other the Multi Initial State Epsilon Nondeterministic finite automaton + * + * \tparam EpsilonType used in the Multi Initial State Epsilon Nondeterministic finite automaton + */ + template < class EpsilonType > + explicit CompactNFA ( const MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & other ); + /* * \brief Creates a new instance of the automaton based on the Epsilon Nondeterministic finite automaton. * @@ -427,6 +437,7 @@ public: } /* namespace automaton */ +#include "MultiInitialStateEpsilonNFA.h" #include "EpsilonNFA.h" #include "MultiInitialStateNFA.h" #include "NFA.h" @@ -442,6 +453,23 @@ template < class SymbolType, class StateType > CompactNFA < SymbolType, StateType >::CompactNFA ( StateType initialState ) : CompactNFA ( ext::set < StateType > { initialState }, ext::set < SymbolType > { }, initialState, ext::set < StateType > { } ) { } +template < class SymbolType, class StateType > +template < class EpsilonType > +CompactNFA < SymbolType, StateType >::CompactNFA ( const MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & other ) : CompactNFA ( other.getStates ( ) + ext::set < StateType > { common::createUnique ( label::InitialStateLabel::instance < StateType > ( ), other.getStates ( ) ) }, other.getInputAlphabet ( ), common::createUnique ( label::InitialStateLabel::instance < StateType > ( ), other.getStates ( ) ), other.getFinalStates ( ) ) { + for ( const auto & transition : other.getTransitions ( ) ) { + if ( transition.first.second.template is < EpsilonType > ( ) ) { + ext::pair < StateType, ext::vector < SymbolType > > key = ext::make_pair ( transition.first.first, ext::vector < SymbolType > { } ); + transitions[key] = transition.second; + } else { + ext::pair < StateType, ext::vector < SymbolType > > key = ext::make_pair ( transition.first.first, ext::vector < SymbolType > { transition.first.second.template get < SymbolType > ( ) } ); + transitions[key] = transition.second; + } + } + + ext::pair < StateType, ext::vector < SymbolType > > key = ext::make_pair ( this->getInitialState ( ), ext::vector < SymbolType > { } ); + transitions[key] = other.getInitialStates ( ); +} + template < class SymbolType, class StateType > template < class EpsilonType > CompactNFA < SymbolType, StateType >::CompactNFA ( const EpsilonNFA < SymbolType, EpsilonType, StateType > & other ) : CompactNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialState ( ), other.getFinalStates ( ) ) { diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.cpp b/alib2data/src/automaton/FSM/ExtendedNFA.cpp index 990f48493d06aab238aaf84305cbead65095057c..5da0b65751759100cde6ffc784cab6dafae6ce18 100644 --- a/alib2data/src/automaton/FSM/ExtendedNFA.cpp +++ b/alib2data/src/automaton/FSM/ExtendedNFA.cpp @@ -17,7 +17,8 @@ static auto valuePrinter = registration::ValuePrinterRegister < automaton::Exten static auto extendedNFAFromDFA = registration::CastRegister < automaton::ExtendedNFA < >, automaton::DFA < > > ( ); static auto extendedNFAFromNFA = registration::CastRegister < automaton::ExtendedNFA < >, automaton::NFA < > > ( ); static auto extendedNFAFromMultiInitialStateNFA = registration::CastRegister < automaton::ExtendedNFA < >, automaton::MultiInitialStateNFA < > > ( ); -static auto extendedNFAEpsilonNFA = registration::CastRegister < automaton::ExtendedNFA < >, automaton::EpsilonNFA < > > ( ); -static auto extendedNFACompactNFA = registration::CastRegister < automaton::ExtendedNFA < >, automaton::CompactNFA < > > ( ); +static auto extendedNFAFromEpsilonNFA = registration::CastRegister < automaton::ExtendedNFA < >, automaton::EpsilonNFA < > > ( ); +static auto extendedNFAFromMultiInitialStateEpsilonNFA = registration::CastRegister < automaton::ExtendedNFA < >, automaton::MultiInitialStateEpsilonNFA < > > ( ); +static auto extendedNFAFromCompactNFA = registration::CastRegister < automaton::ExtendedNFA < >, automaton::CompactNFA < > > ( ); } /* namespace */ diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.h b/alib2data/src/automaton/FSM/ExtendedNFA.h index 949d630b5997d295c275185e2e21c17fd983e164..aaeb716bccc069bedd6c682234f467d11edc9806 100644 --- a/alib2data/src/automaton/FSM/ExtendedNFA.h +++ b/alib2data/src/automaton/FSM/ExtendedNFA.h @@ -102,6 +102,16 @@ public: */ explicit ExtendedNFA ( const CompactNFA < SymbolType, StateType > & other ); + /* + * \brief Creates a new instance of the automaton based on the Multi Initial State Epsilon Nondeterministic finite automaton. + * + * \param other the Multi Initial State Epsilon Nondeterministic finite automaton + * + * \tparam EpsilonType used in the Multi Initial State Epsilon Nondeterministic finite automaton + */ + template < class EpsilonType > + explicit ExtendedNFA ( const MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & other ); + /* * \brief Creates a new instance of the automaton based on the Epsilon Nondeterministic finite automaton. * @@ -465,6 +475,23 @@ ExtendedNFA < SymbolType, StateType >::ExtendedNFA ( const CompactNFA < SymbolTy transitions[key] = transition.second; } } +template < class SymbolType, class StateType > +template < class EpsilonType > +ExtendedNFA < SymbolType, StateType >::ExtendedNFA ( const MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & other ) : ExtendedNFA ( other.getStates ( ) + ext::set < StateType > { common::createUnique ( label::InitialStateLabel::instance < StateType > ( ), other.getStates ( ) ) }, other.getInputAlphabet ( ), common::createUnique ( label::InitialStateLabel::instance < StateType > ( ), other.getStates ( ) ), other.getFinalStates ( ) ) { + for ( const auto & transition : other.getTransitions ( ) ) { + if ( transition.first.second.template is < EpsilonType > ( ) ) { + ext::pair < StateType, regexp::UnboundedRegExpStructure < SymbolType > > key = ext::make_pair ( transition.first.first, regexp::UnboundedRegExpStructure < SymbolType > ( regexp::UnboundedRegExpEpsilon < SymbolType > ( ) ) ); + transitions[key] = transition.second; + } else { + ext::pair < StateType, regexp::UnboundedRegExpStructure < SymbolType > > key = ext::make_pair ( transition.first.first, regexp::UnboundedRegExpStructure < SymbolType > ( regexp::UnboundedRegExpSymbol < SymbolType > ( transition.first.second.template get < SymbolType > ( ) ) ) ); + transitions[key] = transition.second; + } + } + + ext::pair < StateType, regexp::UnboundedRegExpStructure < SymbolType > > key = ext::make_pair ( this->getInitialState ( ), regexp::UnboundedRegExpStructure < SymbolType > ( ) ); + transitions[key] = other.getInitialStates ( ); +} + template < class SymbolType, class StateType > template < class EpsilonType > diff --git a/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.cpp b/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8c5cda1552ab35e52b978664665bc8b87622700f --- /dev/null +++ b/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.cpp @@ -0,0 +1,22 @@ +/* + * MultiInitialStateEpsilonNFA.cpp + * + * Created on: Mar 25, 2013 + * Author: Jan Travnicek + */ + +#include "MultiInitialStateEpsilonNFA.h" + +#include <registration/ValuePrinterRegistration.hpp> +#include <registration/CastRegistration.hpp> + +namespace { + +static auto valuePrinter = registration::ValuePrinterRegister < automaton::MultiInitialStateEpsilonNFA < > > ( ); + +static auto multiInitialStateEpsilonNFAFromDFA = registration::CastRegister < automaton::MultiInitialStateEpsilonNFA < >, automaton::DFA < > > ( ); +static auto multiInitialStateEpsilonNFAFromNFA = registration::CastRegister < automaton::MultiInitialStateEpsilonNFA < >, automaton::NFA < > > ( ); +static auto multiInitialStateEpsilonNFAFromMultiInitialStateNFA = registration::CastRegister < automaton::MultiInitialStateEpsilonNFA < >, automaton::MultiInitialStateNFA < > > ( ); +static auto multiInitialStateEpsilonNFAFromEpsilonNFA = registration::CastRegister < automaton::MultiInitialStateEpsilonNFA < >, automaton::EpsilonNFA < > > ( ); + +} /* namespace */ diff --git a/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h b/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h new file mode 100644 index 0000000000000000000000000000000000000000..6436a0900034214a3c06fe79956145b8c141482c --- /dev/null +++ b/alib2data/src/automaton/FSM/MultiInitialStateEpsilonNFA.h @@ -0,0 +1,1132 @@ +/* + * MultiInitialStateEpsilonNFA.h + * + * This file is part of Algorithms library toolkit. + * Copyright (C) 2017 Jan Travnicek (jan.travnicek@fit.cvut.cz) + + * Algorithms library toolkit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Algorithms library toolkit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with Algorithms library toolkit. If not, see <http://www.gnu.org/licenses/>. + * + * Created on: Mar 25, 2013 + * Author: Jan Travnicek + */ + +#ifndef MULTI_INITIAL_STATE_EPSILON_NFA_H_ +#define MULTI_INITIAL_STATE_EPSILON_NFA_H_ + +#include <alib/map> +#include <alib/set> +#include <alib/variant> +#include <ostream> +#include <sstream> + +#include <core/components.hpp> +#include <common/createUnique.hpp> +#include <object/UniqueObject.h> + +#include "../AutomatonException.h" +#include "../AutomatonBase.h" +#include "../AutomatonFeatures.h" +#include "../common/AutomatonNormalize.h" +#include <alphabet/common/SymbolNormalize.h> + +#include "../../label/InitialStateLabel.h" + +#include <core/normalize.hpp> + +namespace automaton { + +class InputAlphabet; +class States; +class FinalStates; +class InitialStates; + +/** + * \brief + * Epsilon nondeterministic finite automaton. Accepts regular languages. + + * \details + * Definition is classical definition of finite automata. + * A = (Q, T, I, \delta, F), + * Q (States) = nonempty finite set of states, + * T (TerminalAlphabet) = finite set of terminal symbols - having this empty won't let automaton do much though, + * I (InitialStates) = initial states, + * \delta = transition function of the form A \times a -> P(Q), where A \in Q, a \in T \cup \{\epsilon\}, and P(Q) is a powerset of states, + * F (FinalStates) = set of final states + * + * \tparam SymbolType used for the terminal alphabet + * \tparam EpsilonType used for the epislon in the automaton. + * \tparam StateType used to the states, and the initial state of the automaton. + */ +template<class SymbolType, class EpsilonType, class StateType > +class MultiInitialStateEpsilonNFA final : public AutomatonBase, public core::Components < MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >, ext::set < SymbolType >, component::Set, InputAlphabet, ext::set < StateType >, component::Set, std::tuple < States, InitialStates, FinalStates > > { + /** + * Transition function as mapping from a state times an input symbol or epsilon on the left hand side to a set of states. + */ + ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > transitions; + +public: + /** + * \brief Creates a new instance of the automaton with a concrete initial state. + */ + explicit MultiInitialStateEpsilonNFA ( ); + + /** + * \brief Creates a new instance of the automaton with a concrete set of states, input alphabet, initial state, and a set of final states. + * + * \param states the initial set of states of the automaton + * \param inputAlphabet the initial input alphabet + * \param initialState the initial state of the automaton + * \param finalStates the initial set of final states of the automaton + */ + explicit MultiInitialStateEpsilonNFA ( ext::set < StateType > states, ext::set < SymbolType > inputAlphabet, ext::set < StateType > initialState, ext::set < StateType > finalStates ); + + /* + * \brief Creates a new instance of Nondeterministic finite automaton based on the Deterministic finite automaton. + * + * \param other the Nondeterministic finite automaton with multiple initial states + */ + explicit MultiInitialStateEpsilonNFA ( const EpsilonNFA < SymbolType, EpsilonType, StateType > & other ); + + /* + * \brief Creates a new instance of Nondeterministic finite automaton based on the Deterministic finite automaton. + * + * \param other the Nondeterministic finite automaton with multiple initial states + */ + explicit MultiInitialStateEpsilonNFA ( const MultiInitialStateNFA < SymbolType, StateType > & other ); + + /* + * \brief Creates a new instance of Nondeterministic finite automaton based on the Deterministic finite automaton. + * + * \param other the Nondeterministic finite automaton + */ + explicit MultiInitialStateEpsilonNFA ( const NFA < SymbolType, StateType > & other ); + + /* + * \brief creates a new instance of the automaton based on the deterministic finite automaton. + * + * \param other the deterministic finite automaton + */ + explicit MultiInitialStateEpsilonNFA ( const DFA < SymbolType, StateType > & other ); + + /** + * @copydoc automaton::AutomatonBase::clone() + */ + virtual AutomatonBase * clone ( ) const & override; + + /** + * @copydoc automaton::AutomatonBase::clone() + */ + virtual AutomatonBase * clone ( ) && override; + + /** + * Getter of initial states. + * + * \returns the initial states of the automaton + */ + const ext::set < StateType > & getInitialStates ( ) const & { + return this->template accessComponent < InitialStates > ( ).get ( ); + } + + /** + * Getter of initial states. + * + * \returns the initial states of the automaton + */ + ext::set < StateType > && getInitialStates ( ) && { + return std::move ( this->template accessComponent < InitialStates > ( ).get ( ) ); + } + + /** + * Adder of a initial state. + * + * \param state the new state to be added to a set of initial states + * + * \returns true if the state was indeed added + */ + bool addInitialState ( StateType state ) { + return this->template accessComponent < InitialStates > ( ).add ( std::move ( state ) ); + } + + /** + * Setter of initial states. + * + * \param states completely new set of initial states + */ + void setInitialStates ( ext::set < StateType > states ) { + this->template accessComponent < InitialStates > ( ).set ( std::move ( states ) ); + } + + /** + * Remover of a initial state. + * + * \param state a state to be removed from a set of initial states + * + * \returns true if the state was indeed removed + */ + void removeInitialState ( const StateType & state ) { + this->template accessComponent < InitialStates > ( ).remove ( state ); + } + + /** + * Setter of the initial state. + * + * \param state new initial state of the automaton + * + * \returns true if the initial state was indeed changed + */ + bool setInitialState ( StateType state ) { + return this->template accessComponent < InitialStates > ( ).set ( std::move ( state ) ); + } + + /** + * Getter of states. + * + * \returns the states of the automaton + */ + const ext::set < StateType > & getStates ( ) const & { + return this->template accessComponent < States > ( ).get ( ); + } + + /** + * Getter of states. + * + * \returns the states of the automaton + */ + ext::set < StateType > && getStates ( ) && { + return std::move ( this->template accessComponent < States > ( ).get ( ) ); + } + + /** + * Adder of a state. + * + * \param state the new state to be added to a set of states + * + * \returns true if the state was indeed added + */ + bool addState ( StateType state ) { + return this->template accessComponent < States > ( ).add ( std::move ( state ) ); + } + + /** + * Setter of states. + * + * \param states completely new set of states + */ + void setStates ( ext::set < StateType > states ) { + this->template accessComponent < States > ( ).set ( std::move ( states ) ); + } + + /** + * Remover of a state. + * + * \param state a state to be removed from a set of states + * + * \returns true if the state was indeed removed + */ + void removeState ( const StateType & state ) { + this->template accessComponent < States > ( ).remove ( state ); + } + + /** + * Getter of final states. + * + * \returns the final states of the automaton + */ + const ext::set < StateType > & getFinalStates ( ) const & { + return this->template accessComponent < FinalStates > ( ).get ( ); + } + + /** + * Getter of final states. + * + * \returns the final states of the automaton + */ + ext::set < StateType > && getFinalStates ( ) && { + return std::move ( this->template accessComponent < FinalStates > ( ).get ( ) ); + } + + /** + * Adder of a final state. + * + * \param state the new state to be added to a set of final states + * + * \returns true if the state was indeed added + */ + bool addFinalState ( StateType state ) { + return this->template accessComponent < FinalStates > ( ).add ( std::move ( state ) ); + } + + /** + * Setter of final states. + * + * \param states completely new set of final states + */ + void setFinalStates ( ext::set < StateType > states ) { + this->template accessComponent < FinalStates > ( ).set ( std::move ( states ) ); + } + + /** + * Remover of a final state. + * + * \param state a state to be removed from a set of final states + * + * \returns true if the state was indeed removed + */ + void removeFinalState ( const StateType & state ) { + this->template accessComponent < FinalStates > ( ).remove ( state ); + } + + /** + * Getter of the input alphabet. + * + * \returns the input alphabet of the automaton + */ + const ext::set < SymbolType > & getInputAlphabet ( ) const & { + return this->template accessComponent < InputAlphabet > ( ).get ( ); + } + + /** + * Getter of the input alphabet. + * + * \returns the input alphabet of the automaton + */ + ext::set < SymbolType > && getInputAlphabet ( ) && { + return std::move ( this->template accessComponent < InputAlphabet > ( ).get ( ) ); + } + + /** + * Adder of a input symbol. + * + * \param symbol the new symbol to be added to an input alphabet + * + * \returns true if the symbol was indeed added + */ + bool addInputSymbol ( SymbolType symbol ) { + return this->template accessComponent < InputAlphabet > ( ).add ( std::move ( symbol ) ); + } + + /** + * Adder of input symbols. + * + * \param symbols new symbols to be added to an input alphabet + */ + void addInputSymbols ( ext::set < SymbolType > symbols ) { + this->template accessComponent < InputAlphabet > ( ).add ( std::move ( symbols ) ); + } + + /** + * Setter of input alphabet. + * + * \param symbols completely new input alphabet + */ + void setInputAlphabet ( ext::set < SymbolType > symbols ) { + this->template accessComponent < InputAlphabet > ( ).set ( std::move ( symbols ) ); + } + + /** + * Remover of an input symbol. + * + * \param symbol a symbol to be removed from an input alphabet + * + * \returns true if the symbol was indeed removed + */ + void removeInputSymbol ( const SymbolType & symbol ) { + this->template accessComponent < InputAlphabet > ( ).remove ( symbol ); + } + + /** + * \brief Add a transition to the automaton. + * + * \details The transition is in a form A \times a -> B, where A, B \in Q and a \in T \cup \{\epsilon\} + * + * \param current the source state (A) + * \param input the input symbol or epsilon (a) + * \param next the target state (B) + * + * \throws AutomatonException when transition contains state or symbol not present in the automaton components + * + * \returns true if the transition was indeed added + */ + bool addTransition ( StateType from, ext::variant < EpsilonType, SymbolType > input, StateType to ); + + /** + * \brief Add a transition to the automaton. + * + * \details The transition is in a form A \times a -> B, where A, B \in Q and a \in T + * + * \param current the source state (A) + * \param input the input symbol (a) + * \param next the target state (B) + * + * \throws AutomatonException when transition contains state or symbol not present in the automaton components + * + * \returns true if the transition was indeed added + */ + bool addTransition ( StateType from, SymbolType input, StateType to ); + + /** + * \brief Add a transition to the automaton. + * + * \details The transition is in a form A \times \epsilon -> B, where A, B \in Q + * + * \param current the source state (A) + * \param next the target state (B) + * + * \throws AutomatonException when transition contains state or symbol not present in the automaton components + * + * \returns true if the transition was indeed added + */ + bool addTransition ( StateType from, StateType to ); + + /** + * \brief Add a transitions to the automaton. + * + * \details The transition is in a form A \times a -> P(Q), where A \in Q, a \in T \cup \{\epsilon\}, P(Q) is a powerset of states. + * + * \param current the source state (A) + * \param input the input symbol or epsilon (a) + * \param next the target states (P(Q)) + * + * \throws AutomatonException when transitions contain states or symbols not present in the automaton components + */ + void addTransitions ( StateType from, ext::variant < EpsilonType, SymbolType > input, ext::set < StateType > to ); + + /** + * \brief Add a transitions to the automaton. + * + * \details The transition is in a form A \times a -> P(Q), where A \in Q, a \in T, P(Q) is a powerset of states. + * + * \param current the source state (A) + * \param input the input symbol (a) + * \param next the target states (P(Q)) + * + * \throws AutomatonException when transitions contain states or symbols not present in the automaton components + */ + void addTransitions ( StateType from, SymbolType input, ext::set < StateType > to ); + + /** + * \brief Add a transitions to the automaton. + * + * \details The transition is in a form A \times \epsilon -> P(Q), where A \in Q, P(Q) is a powerset of states. + * + * \param current the source state (A) + * \param next the target states (P(Q)) + * + * \throws AutomatonException when transitions contain states or symbols not present in the automaton components + */ + void addTransitions ( StateType from, ext::set < StateType > to ); + + /** + * \brief Removes a transition from the automaton. + * + * \details The transition is in a form A \times a -> B, where A, B \in Q and a \in T + * + * \param current the source state (A) + * \param input the input symbol (a) + * \param next the target state (B) + * + * \returns true if the transition was indeed removed + */ + bool removeTransition ( const StateType & current, const SymbolType & input, const StateType & next ); + + /** + * \brief Removes a transition from the automaton. + * + * \details The transition is in a form A \times \epsilon -> B, where A, B \in Q + * + * \param current the source state (A) + * \param next the target state (B) + * + * \returns true if the transition was indeed removed + */ + bool removeTransition ( const StateType & current, const StateType & next ); + + /** + * Get the transition function of the automaton in its natural form. + * + * \returns transition function of the automaton + */ + const ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & getTransitions ( ) const &; + + /** + * Get the transition function of the automaton in its natural form. + * + * \returns transition function of the automaton + */ + ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > && getTransitions ( ) &&; + + /** + * Get the epsilon transitions of the automaton + * + * \returns epsilon transitions of the automaton + */ + ext::map < StateType, ext::set < StateType > > getEpsilonTransitions ( ) const; + + /** + * Get the non-epsilon transitions of the automaton + * + * \returns non-epsilon transitions of the automaton + */ + ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > getSymbolTransitions ( ) const; + + /** + * Get a subset of the transition function of the automaton, with the source state fixed in the transitions natural representation. + * + * \param from filter the transition function based on this state as a source state + * + * \returns a subset of the transition function of the automaton with the source state fixed + */ + ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > getTransitionsFromState ( const StateType & from ) const; + + /** + * Get a subset of epsilon transitions of the automaton, with the source state fixed in the transitions natural representation. + * + * \param from filter the transition function based on this state as a source state + * + * \returns a subset of epsilon transitions of the automaton with the source state fixed + */ + ext::map < StateType, ext::set < StateType > > getEpsilonTransitionsFromState ( const StateType & from ) const; + + /** + * Get a subset of non-epsilon transitions of the automaton, with the source state fixed in the transitions natural representation. + * + * \param from filter the transition function based on this state as a source state + * + * \returns a subset of non-epsilon transitions of the automaton with the source state fixed + */ + ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > getSymbolTransitionsFromState ( const StateType & from ) const; + + /** + * Get a subset of the transition function of the automaton, with the target state fixed in the transitions natural representation. + * + * \param to filter the transition function based on this state as a source state + * + * \returns a subset of the transition function of the automaton with the target state fixed + */ + ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > getTransitionsToState ( const StateType & from ) const; + + /** + * Get a subset of epsilon transitions of the automaton, with the target state fixed in the transitions natural representation. + * + * \param to filter the transition function based on this state as a source state + * + * \returns a subset of epsilon transitions of the automaton with the target state fixed + */ + ext::map < StateType, ext::set < StateType > > getEpsilonTransitionsToState ( const StateType & to ) const; + + /** + * Get a subset of non-epsilon transitions of the automaton, with the target state fixed in the transitions natural representation. + * + * \param to filter the transition function based on this state as a source state + * + * \returns a subset of non-epsilon transitions of the automaton with the target state fixed + */ + ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > getSymbolTransitionsToState ( const StateType & to ) const; + + /** + * \brief Determines whether the automaton is without epsilon transitions. + * + * \return true when automaton doesn't contain epsilon transitions, false otherwise + */ + bool isEpsilonFree ( ) const; + + /** + * \brief Determines whether the automaton is deterministic + * + * The automaton is deterministic if and only if: + * \li \c is epsilon free. + * \li \c size of transition function \delta (from state, input symbol) \leq 1 + * + * \return true if the automaton is deterministic, false otherwise + */ + bool isDeterministic ( ) const; + + /** + * \brief Determines whether the automaton is total deterministic + * + * The automaton is deterministic if and only if: + * \li \c it is deterministic + * \li \c size of transition function \forall states and \forall input symbols \delta (from state, input symbol) = 1 + * + * \return true if the automaton is total deterministic, false otherwise + */ + bool isTotal ( ) const; + + /** + * @copydoc base::CommonBase < ObjectBase >::compare ( const ObjectBase & ) + */ + virtual int compare ( const ObjectBase & other ) const override { + if ( ext::type_index ( typeid ( * this ) ) == ext::type_index ( typeid ( other ) ) ) return this->compare ( ( decltype ( * this ) )other ); + + return ext::type_index ( typeid ( * this ) ) - ext::type_index ( typeid ( other ) ); + } + + /** + * The actual compare method + * + * \param other the other instance + * + * \returns the actual relation between two by type same automata instances + */ + virtual int compare ( const MultiInitialStateEpsilonNFA & other ) const; + + /** + * @copydoc base::CommonBase < ObjectBase >::operator >> ( std::ostream & ) + */ + virtual void operator >>( std::ostream & os ) const override; + + /** + * @copydoc base::CommonBase < ObjectBase >::operator std::string ( ) + */ + virtual explicit operator std::string ( ) const override; + + /** + * @copydoc object::ObjectBase::inc() + */ + virtual object::ObjectBase * inc ( ) && override; +}; + +} /* namespace automaton */ + +#include "EpsilonNFA.h" +#include "MultiInitialStateNFA.h" +#include "NFA.h" +#include "DFA.h" + +namespace automaton { + +template<class SymbolType, class EpsilonType, class StateType > +MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::MultiInitialStateEpsilonNFA ( ext::set < StateType > states, ext::set < SymbolType > inputAlphabet, ext::set < StateType > initialStates, ext::set < StateType > finalStates ) : core::Components < MultiInitialStateEpsilonNFA, ext::set < SymbolType >, component::Set, InputAlphabet, ext::set < StateType >, component::Set, std::tuple < States, InitialStates, FinalStates > > ( std::move ( inputAlphabet ), std::move ( states ), std::move ( initialStates ), std::move ( finalStates ) ) { +} + +template<class SymbolType, class EpsilonType, class StateType > +MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::MultiInitialStateEpsilonNFA ( ) : MultiInitialStateEpsilonNFA ( ext::set < StateType > { }, ext::set < SymbolType > { }, ext::set < StateType > { }, ext::set < StateType > { } ) { +} + +template<class SymbolType, class EpsilonType, class StateType > +MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::MultiInitialStateEpsilonNFA ( const EpsilonNFA < SymbolType, EpsilonType, StateType > & other ) : MultiInitialStateEpsilonNFA ( other.getStates ( ), other.getInputAlphabet ( ), { other.getInitialState ( ) }, other.getFinalStates ( ) ) { + for ( const auto & transition : other.getTransitions ( ) ) { + ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key = ext::make_pair ( transition.first.first, ext::variant < EpsilonType, SymbolType > ( transition.first.second ) ); + transitions[key] = transition.second; + } +} + +template<class SymbolType, class EpsilonType, class StateType > +MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::MultiInitialStateEpsilonNFA ( const MultiInitialStateNFA < SymbolType, StateType > & other ) : MultiInitialStateEpsilonNFA ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialStates ( ), other.getFinalStates ( ) ) { + for ( const auto & transition : other.getTransitions ( ) ) { + ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key = ext::make_pair ( transition.first.first, ext::variant < EpsilonType, SymbolType > ( transition.first.second ) ); + transitions[key] = transition.second; + } +} + +template<class SymbolType, class EpsilonType, class StateType > +MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::MultiInitialStateEpsilonNFA ( const NFA < SymbolType, StateType > & other ) : MultiInitialStateEpsilonNFA ( other.getStates ( ), other.getInputAlphabet ( ), { other.getInitialState ( ) }, other.getFinalStates ( ) ) { + for ( const auto & transition : other.getTransitions ( ) ) { + ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key = ext::make_pair ( transition.first.first, ext::variant < EpsilonType, SymbolType > ( transition.first.second ) ); + transitions[key] = transition.second; + } +} + +template<class SymbolType, class EpsilonType, class StateType > +MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::MultiInitialStateEpsilonNFA ( const DFA < SymbolType, StateType > & other ) : MultiInitialStateEpsilonNFA ( other.getStates ( ), other.getInputAlphabet ( ), { other.getInitialState ( ) }, other.getFinalStates ( ) ) { + for ( const auto & transition : other.getTransitions ( ) ) { + ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key = ext::make_pair ( transition.first.first, ext::variant < EpsilonType, SymbolType > ( transition.first.second ) ); + transitions[key].insert ( transition.second ); + } +} + +template<class SymbolType, class EpsilonType, class StateType > +AutomatonBase * MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::clone ( ) const & { + return new MultiInitialStateEpsilonNFA ( * this ); +} + +template<class SymbolType, class EpsilonType, class StateType > +AutomatonBase * MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::clone ( ) && { + return new MultiInitialStateEpsilonNFA ( std::move ( * this ) ); +} + +template<class SymbolType, class EpsilonType, class StateType > +bool MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::addTransition ( StateType from, ext::variant < EpsilonType, SymbolType > input, StateType to ) { + if ( !getStates ( ).count ( from ) ) + throw AutomatonException ( "State \"" + ext::to_string ( from ) + "\" doesn't exist." ); + + if ( input.template is < SymbolType > ( ) && !getInputAlphabet ( ).count ( input.template get < SymbolType > ( ) ) ) + throw AutomatonException ( "Input symbol \"" + ext::to_string ( input ) + "\" doesn't exist." ); + + if ( !getStates ( ).count ( to ) ) + throw AutomatonException ( "State \"" + ext::to_string ( to ) + "\" doesn't exist." ); + + ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key = ext::make_pair ( std::move ( from ), std::move ( input ) ); + + return transitions[std::move ( key )].insert ( std::move ( to ) ).second; +} + +template<class SymbolType, class EpsilonType, class StateType > +bool MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::addTransition ( StateType from, SymbolType input, StateType to ) { + ext::variant < EpsilonType, SymbolType > inputVariant ( std::move ( input ) ); + + return addTransition ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) ); +} + +template<class SymbolType, class EpsilonType, class StateType > +bool MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::addTransition ( StateType from, StateType to ) { + auto inputVariant = ext::variant < EpsilonType, SymbolType >::template from < EpsilonType > ( ); + + return addTransition ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) ); +} + +template < class SymbolType, class EpsilonType, class StateType > +void MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::addTransitions ( StateType from, ext::variant < EpsilonType, SymbolType > input, ext::set < StateType > to ) { + if ( !getStates ( ).count ( from ) ) + throw AutomatonException ( "State \"" + ext::to_string ( from ) + "\" doesn't exist." ); + + if ( input.template is < SymbolType > ( ) && !getInputAlphabet ( ).count ( input.template get < SymbolType > ( ) ) ) + throw AutomatonException ( "Input symbol \"" + ext::to_string ( input ) + "\" doesn't exist." ); + + if ( !std::includes ( getStates ( ).begin ( ), getStates ( ).end ( ), to.begin ( ), to.end ( ) ) ) + throw AutomatonException ( "Some target states don't exist." ); + + ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key = ext::make_pair ( std::move ( from ), std::move ( input ) ); + + transitions [ std::move ( key ) ].insert ( ext::make_moveable_set ( to ).begin ( ), ext::make_moveable_set ( to ).end ( ) ); +} + +template<class SymbolType, class EpsilonType, class StateType > +void MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::addTransitions ( StateType from, SymbolType input, ext::set < StateType > to ) { + ext::variant < EpsilonType, SymbolType > inputVariant ( std::move ( input ) ); + + addTransitions ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) ); +} + +template<class SymbolType, class EpsilonType, class StateType > +void MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::addTransitions ( StateType from, ext::set < StateType > to ) { + auto inputVariant = ext::variant < EpsilonType, SymbolType >::template from < EpsilonType > ( ); + + addTransitions ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) ); +} + +template<class SymbolType, class EpsilonType, class StateType > +bool MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::removeTransition ( const StateType & from, const SymbolType & input, const StateType & to ) { + ext::variant < EpsilonType, SymbolType > inputVariant ( input ); + ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key = ext::make_pair ( from, inputVariant ); + + return transitions[key].erase ( to ); +} + +template<class SymbolType, class EpsilonType, class StateType > +bool MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::removeTransition ( const StateType & from, const StateType & to ) { + auto inputVariant = ext::variant < EpsilonType, SymbolType >::template from < EpsilonType > ( ); + + ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key = ext::make_pair ( from, inputVariant ); + + return transitions[key].erase ( to ); +} + +template<class SymbolType, class EpsilonType, class StateType > +const ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitions ( ) const & { + return transitions; +} + +template<class SymbolType, class EpsilonType, class StateType > +ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > && MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitions ( ) && { + return std::move ( transitions ); +} + +template<class SymbolType, class EpsilonType, class StateType > +ext::map < StateType, ext::set < StateType > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitions ( ) const { + ext::map < StateType, ext::set < StateType > > result; + + for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions ) + if ( transition.first.second.template is < EpsilonType > ( ) ) + result[transition.first.first].insert ( transition.second.begin ( ), transition.second.end ( ) ); + + return result; +} + +template<class SymbolType, class EpsilonType, class StateType > +ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitions ( ) const { + ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > result; + + for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions ) + if ( transition.first.second.template is < SymbolType > ( ) ) + result[ext::pair < StateType, SymbolType > ( transition.first.first, transition.first.second.template get < SymbolType > ( ) )].insert ( transition.second.begin ( ), transition.second.end ( ) ); + + return result; +} + +template<class SymbolType, class EpsilonType, class StateType > +ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitionsFromState ( const StateType & from ) const { + if ( !getStates ( ).count ( from ) ) + throw AutomatonException ( "State \"" + ext::to_string ( from ) + "\" doesn't exist" ); + + ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > transitionsFromState; + + for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions ) + if ( transition.first.first == from ) + transitionsFromState[transition.first].insert ( transition.second.begin ( ), transition.second.end ( ) ); + + return transitionsFromState; +} + +template<class SymbolType, class EpsilonType, class StateType > +ext::map < StateType, ext::set < StateType > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitionsFromState ( const StateType & from ) const { + if ( !getStates ( ).count ( from ) ) + throw AutomatonException ( "State \"" + ext::to_string ( from ) + "\" doesn't exist" ); + + ext::pair < StateType, ext::variant < EpsilonType, SymbolType > > key ( from, ext::variant < EpsilonType, SymbolType >::template from < EpsilonType > ( ) ); + ext::map < StateType, ext::set < StateType > > res; + auto transition = transitions.find ( key ); + + if ( transition != transitions.end ( ) ) + res.insert ( std::make_pair ( from, transition->second ) ); + + return res; +} + +template<class SymbolType, class EpsilonType, class StateType > +ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitionsFromState ( const StateType & from ) const { + if ( !getStates ( ).count ( from ) ) + throw AutomatonException ( "State \"" + ext::to_string ( from ) + "\" doesn't exist" ); + + ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > transitionsFromState; + + for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions ) + if ( ( transition.first.first == from ) && transition.first.second.template is < SymbolType > ( ) ) + transitionsFromState[ext::pair < StateType, SymbolType > ( transition.first.first, transition.first.second.template get < SymbolType > ( ) )].insert ( transition.second.begin ( ), transition.second.end ( ) ); + + return transitionsFromState; +} + +template<class SymbolType, class EpsilonType, class StateType > +ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getTransitionsToState ( const StateType & to ) const { + if ( !getStates ( ).count ( to ) ) + throw AutomatonException ( "State \"" + ext::to_string ( to ) + "\" doesn't exist" ); + + ext::map < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > transitionsToState; + + for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions ) + if ( transition.second.find ( to ) != transition.second.end ( ) ) + transitionsToState[transition.first].insert ( transition.second.begin ( ), transition.second.end ( ) ); + + return transitionsToState; +} + +template<class SymbolType, class EpsilonType, class StateType > +ext::map < StateType, ext::set < StateType > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getEpsilonTransitionsToState ( const StateType & to ) const { + if ( !getStates ( ).count ( to ) ) + throw AutomatonException ( "State \"" + ext::to_string ( to ) + "\" doesn't exist" ); + + ext::map < StateType, ext::set < StateType > > transitionsToState; + + for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions ) + if ( ( transition.second.find ( to ) != transition.second.end ( ) ) && transition.first.second.template is < EpsilonType > ( ) ) + transitionsToState[transition.first.first].insert ( transition.second.begin ( ), transition.second.end ( ) ); + + return transitionsToState; +} + +template<class SymbolType, class EpsilonType, class StateType > +ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::getSymbolTransitionsToState ( const StateType & to ) const { + if ( !getStates ( ).count ( to ) ) + throw AutomatonException ( "State \"" + ext::to_string ( to ) + "\" doesn't exist" ); + + ext::map < ext::pair < StateType, SymbolType >, ext::set < StateType > > transitionsToState; + + for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions ) + if ( ( transition.second.find ( to ) != transition.second.end ( ) ) && transition.first.second.template is < SymbolType > ( ) ) + transitionsToState[ext::pair < StateType, SymbolType > ( transition.first.first, transition.first.second.template get < SymbolType > ( ) )].insert ( transition.second.begin ( ), transition.second.end ( ) ); + + return transitionsToState; +} + +template<class SymbolType, class EpsilonType, class StateType > +bool MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::isEpsilonFree ( ) const { + for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions ) + if ( transition.first.second.template is < EpsilonType > ( ) ) + return false; + + return true; +} + +template<class SymbolType, class EpsilonType, class StateType > +bool MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::isDeterministic ( ) const { + for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : transitions ) + if ( transition.second.size ( ) > 1 ) + return false; + + return isEpsilonFree ( ); +} + +template<class SymbolType, class EpsilonType, class StateType > +bool MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::isTotal ( ) const { + return isDeterministic ( ) && transitions.size ( ) == getInputAlphabet ( ).size ( ) * getStates ( ).size ( ); +} + +template<class SymbolType, class EpsilonType, class StateType > +int MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::compare ( const MultiInitialStateEpsilonNFA & other ) const { + auto first = ext::tie ( getStates ( ), getInputAlphabet ( ), getInitialStates ( ), getFinalStates ( ), transitions ); + auto second = ext::tie ( other.getStates ( ), other.getInputAlphabet ( ), other.getInitialStates ( ), other.getFinalStates ( ), other.getTransitions ( ) ); + + static ext::compare < decltype ( first ) > comp; + + return comp ( first, second ); +} + +template<class SymbolType, class EpsilonType, class StateType > +void MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::operator >>( std::ostream & out ) const { + out << "(MultiInitialStateEpsilonNFA " + << "states = " << getStates ( ) + << "inputAlphabet = " << getInputAlphabet ( ) + << "initialState = " << getInitialStates ( ) + << "finalStates = " << getFinalStates ( ) + << "transitions = " << transitions + << ")"; +} + +template<class SymbolType, class EpsilonType, class StateType > +MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::operator std::string ( ) const { + std::stringstream ss; + ss << * this; + return ss.str ( ); +} + +template < class SymbolType, class EpsilonType, class StateType > +object::ObjectBase* MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >::inc() && { + return new object::UniqueObject(object::Object(std::move(*this)), primitive::Integer(0)); +} + +} /* namespace automaton */ + +namespace core { + +/** + * Helper class specifying constraints for the automaton's internal input alphabet component. + * + * \tparam SymbolType used for the terminal alphabet of the automaton. + * \tparam EpsilonType used for the epislon in the automaton. + * \tparam StateType used for the terminal alphabet of the automaton. + */ +template<class SymbolType, class EpsilonType, class StateType > +class SetConstraint< automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >, SymbolType, automaton::InputAlphabet > { +public: + /** + * Returns true if the symbol is still used in some transition of the automaton. + * + * \param automaton the tested automaton + * \param symbol the tested symbol + * + * \returns true if the symbol is used, false othervise + */ + static bool used ( const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & automaton, const SymbolType & symbol ) { + for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : automaton.getTransitions ( ) ) + if ( transition.first.second.template is < SymbolType > ( ) && ( transition.first.second.template get < SymbolType > ( ) == symbol ) ) + return true; + + return false; + } + + /** + * Returns true as all symbols are possibly available to be elements of the input alphabet. + * + * \param automaton the tested automaton + * \param symbol the tested symbol + * + * \returns true + */ + static bool available ( const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > &, const SymbolType & ) { + return true; + } + + /** + * All symbols are valid as input symbols. + * + * \param automaton the tested automaton + * \param symbol the tested symbol + */ + static void valid ( const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > &, const SymbolType & ) { + } +}; + +/** + * Helper class specifying constraints for the automaton's internal states component. + * + * \tparam SymbolType used for the terminal alphabet of the automaton. + * \tparam EpsilonType used for the epislon in the automaton. + * \tparam StateType used for the terminal alphabet of the automaton. + */ +template<class SymbolType, class EpsilonType, class StateType > +class SetConstraint< automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >, StateType, automaton::States > { +public: + /** + * Returns true if the state is still used in some transition of the automaton. + * + * \param automaton the tested automaton + * \param state the tested state + * + * \returns true if the state is used, false othervise + */ + static bool used ( const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & automaton, const StateType & state ) { + if ( automaton.getInitialStates ( ).count ( state ) ) + return true; + + if ( automaton.getFinalStates ( ).count ( state ) ) + return true; + + for ( const std::pair < const ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > & transition : automaton.getTransitions ( ) ) + if ( ( transition.first.first == state ) || transition.second.count ( state ) ) + return true; + + return false; + } + + /** + * Returns true as all states are possibly available to be elements of the states. + * + * \param automaton the tested automaton + * \param state the tested state + * + * \returns true + */ + static bool available ( const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > &, const StateType & ) { + return true; + } + + /** + * All states are valid as a state of the automaton. + * + * \param automaton the tested automaton + * \param state the tested state + */ + static void valid ( const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > &, const StateType & ) { + } +}; + +/** + * Helper class specifying constraints for the automaton's internal final states component. + * + * \tparam SymbolType used for the terminal alphabet of the automaton. + * \tparam EpsilonType used for the epislon in the automaton. + * \tparam StateType used for the terminal alphabet of the automaton. + */ +template<class SymbolType, class EpsilonType, class StateType > +class SetConstraint< automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >, StateType, automaton::FinalStates > { +public: + /** + * Returns false. Final state is only a mark that the automaton itself does require further. + * + * \param automaton the tested automaton + * \param state the tested state + * + * \returns false + */ + static bool used ( const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > &, const StateType & ) { + return false; + } + + /** + * Determines whether the state is available in the automaton's states set. + * + * \param automaton the tested automaton + * \param state the tested state + * + * \returns true if the state is already in the set of states of the automaton + */ + static bool available ( const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & automaton, const StateType & state ) { + return automaton.template accessComponent < automaton::States > ( ).get ( ).count ( state ); + } + + /** + * All states are valid as a final state of the automaton. + * + * \param automaton the tested automaton + * \param state the tested state + */ + static void valid ( const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > &, const StateType & ) { + } +}; + +/** + * Helper class specifying constraints for the automaton's internal final states component. + * + * \tparam SymbolType used for the terminal alphabet of the automaton. + * \tparam EpsilonType used for the epislon in the automaton. + * \tparam StateType used for the terminal alphabet of the automaton. + */ +template<class SymbolType, class EpsilonType, class StateType > +class SetConstraint< automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType >, StateType, automaton::InitialStates > { +public: + /** + * Returns false. Initial state is only a mark that the automaton itself does require further. + * + * \param automaton the tested automaton + * \param state the tested state + * + * \returns false + */ + static bool used ( const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > &, const StateType & ) { + return false; + } + + /** + * Determines whether the state is available in the automaton's states set. + * + * \param automaton the tested automaton + * \param state the tested state + * + * \returns true if the state is already in the set of states of the automaton + */ + static bool available ( const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & automaton, const StateType & state ) { + return automaton.template accessComponent < automaton::States > ( ).get ( ).count ( state ); + } + + /** + * All states are valid as a initial state of the automaton. + * + * \param automaton the tested automaton + * \param state the tested state + */ + static void valid ( const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > &, const StateType & ) { + } +}; + +/** + * Helper for normalisation of types specified by templates used as internal datatypes of symbols and states. + * + * \returns new instance of the automaton with default template parameters or unmodified instance if the template parameters were already the default ones + */ +template<class SymbolType, class EpsilonType, class StateType > +struct normalize < automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > > { + static automaton::MultiInitialStateEpsilonNFA < > eval ( automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > && value ) { + ext::set < DefaultSymbolType > alphabet = alphabet::SymbolNormalize::normalizeAlphabet ( std::move ( value ).getInputAlphabet ( ) ); + ext::set < DefaultStateType > states = automaton::AutomatonNormalize::normalizeStates ( std::move ( value ).getStates ( ) ); + ext::set < DefaultStateType > initialStates = automaton::AutomatonNormalize::normalizeState ( std::move ( value ).getInitialStates ( ) ); + ext::set < DefaultStateType > finalStates = automaton::AutomatonNormalize::normalizeStates ( std::move ( value ).getFinalStates ( ) ); + + automaton::MultiInitialStateEpsilonNFA < > res ( std::move ( states ), std::move ( alphabet ), std::move ( initialStates ), std::move ( finalStates ) ); + + for ( std::pair < ext::pair < StateType, ext::variant < EpsilonType, SymbolType > >, ext::set < StateType > > && transition : ext::make_moveable_map ( std::move ( value ).getTransitions ( ) ) ) { + DefaultStateType from = automaton::AutomatonNormalize::normalizeState ( std::move ( transition.first.first ) ); + ext::variant < DefaultEpsilonType, DefaultSymbolType > input = automaton::AutomatonNormalize::normalizeSymbolEpsilon ( std::move ( transition.first.second ) ); + ext::set < DefaultStateType > targets = automaton::AutomatonNormalize::normalizeStates ( std::move ( transition.second ) ); + + res.addTransitions ( std::move ( from ), std::move ( input ), std::move ( targets ) ); + } + + return res; + } +}; + +} /* namespace core */ + +#endif /* MULTI_INITIAL_STATE_EPSILON_NFA_H_ */ diff --git a/alib2data/src/automaton/xml/FSM/MultiInitialStateEpsilonNFA.cpp b/alib2data/src/automaton/xml/FSM/MultiInitialStateEpsilonNFA.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2e59c648e70356875d05a7f2232fa46b8696fb9e --- /dev/null +++ b/alib2data/src/automaton/xml/FSM/MultiInitialStateEpsilonNFA.cpp @@ -0,0 +1,22 @@ +/* + * MultiInitialStateEpsilonNFA.cpp + * + * Created on: Mar 25, 2013 + * Author: Jan Travnicek + */ + +#include "MultiInitialStateEpsilonNFA.h" +#include <automaton/Automaton.h> +#include <object/Object.h> + +#include <registration/XmlRegistration.hpp> + +namespace { + +static auto xmlWrite = registration::XmlWriterRegister < automaton::MultiInitialStateEpsilonNFA < > > ( ); +static auto xmlRead = registration::XmlReaderRegister < automaton::MultiInitialStateEpsilonNFA < > > ( ); + +static auto xmlGroup1 = registration::XmlRegisterTypeInGroup < automaton::Automaton, automaton::MultiInitialStateEpsilonNFA < > > ( ); +static auto xmlGroup2 = registration::XmlRegisterTypeInGroup < object::Object, automaton::MultiInitialStateEpsilonNFA < > > ( ); + +} /* namespace */ diff --git a/alib2data/src/automaton/xml/FSM/MultiInitialStateEpsilonNFA.h b/alib2data/src/automaton/xml/FSM/MultiInitialStateEpsilonNFA.h new file mode 100644 index 0000000000000000000000000000000000000000..f842c3e8eed9e7f0a7dd372fb84f3c8a09f10aa1 --- /dev/null +++ b/alib2data/src/automaton/xml/FSM/MultiInitialStateEpsilonNFA.h @@ -0,0 +1,160 @@ +/* + * MultiInitialStateEpsilonNFA.h + * + * This file is part of Algorithms library toolkit. + * Copyright (C) 2017 Jan Travnicek (jan.travnicek@fit.cvut.cz) + + * Algorithms library toolkit is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Algorithms library toolkit is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with Algorithms library toolkit. If not, see <http://www.gnu.org/licenses/>. + * + * Created on: Mar 25, 2013 + * Author: Jan Travnicek + */ + +#ifndef _XML_MULTI_INITIAL_STATE_EPSILON_NFA_H_ +#define _XML_MULTI_INITIAL_STATE_EPSILON_NFA_H_ + +#include <core/xmlApi.hpp> +#include <automaton/FSM/MultiInitialStateEpsilonNFA.h> +#include "../common/AutomatonFromXMLParser.h" +#include "../common/AutomatonToXMLComposer.h" + +namespace core { + +template < class SymbolType, class EpsilonType, class StateType > +struct xmlApi < automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > > { + /** + * \brief The XML tag name of class. + * + * \details Intentionaly a static member function to be safe in the initialisation before the main function starts. + * + * \returns string representing the XML tag name of the class + */ + static const std::string & xmlTagName() { + static std::string xmlTagName = "MultiInitialStateEpsilonNFA"; + + return xmlTagName; + } + + /** + * \brief Tests whether the token stream starts with this type + * + * \params input the iterator to sequence of xml tokens to test + * + * \returns true if the token stream iterator points to opening tag named with xml tag name of this type, false otherwise. + */ + static bool first ( const ext::deque < sax::Token >::const_iterator & input ) { + return sax::FromXMLParserHelper::isToken ( input, sax::Token::TokenType::START_ELEMENT, xmlTagName ( ) ); + } + + /** + * Parsing from a sequence of xml tokens helper. + * + * \params input the iterator to sequence of xml tokens to parse from + * + * \returns the new instance of the automaton + */ + static automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > parse ( ext::deque < sax::Token >::iterator & input ); + + /** + * Helper for parsing of individual transitions of the automaton from a sequence of xml tokens. + * + * \params input the iterator to sequence of xml tokens to parse from + * \params automaton the automaton to add the rule to + */ + static void parseTransition ( ext::deque < sax::Token >::iterator & input, automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & automaton ); + + /** + * Composing to a sequence of xml tokens helper. + * + * \param out the sink for new xml tokens representing the automaton + * \param automaton the automaton to compose + */ + static void compose ( ext::deque < sax::Token > & out, const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & automaton ); + + /** + * Helper for composing transitions of the automaton to a sequence of xml tokens. + * + * \param out the sink for xml tokens representing the rules of the automaton + * \param automaton the automaton to compose + */ + static void composeTransitions ( ext::deque < sax::Token > & out, const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & automaton ); +}; + +template < class SymbolType, class EpsilonType, class StateType > +automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > xmlApi < automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > >::parse ( ext::deque < sax::Token >::iterator & input ) { + sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, xmlTagName ( ) ); + + ext::set < StateType > states = automaton::AutomatonFromXMLParser::parseStates < StateType > ( input ); + ext::set < SymbolType > inputSymbols = automaton::AutomatonFromXMLParser::parseInputAlphabet < SymbolType > ( input ); + ext::set < StateType > initialStates = automaton::AutomatonFromXMLParser::parseInitialStates < StateType > ( input ); + ext::set < StateType > finalStates = automaton::AutomatonFromXMLParser::parseFinalStates < StateType > ( input ); + + automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > automaton; + + automaton.setStates ( std::move ( states ) ); + automaton.setInputAlphabet ( std::move ( inputSymbols ) ); + automaton.setInitialStates ( std::move ( initialStates ) ); + automaton.setFinalStates ( std::move ( finalStates ) ); + + automaton::AutomatonFromXMLParser::parseTransitions ( input, automaton ); + + sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, xmlTagName() ); + return automaton; +} + +template < class SymbolType, class EpsilonType, class StateType > +void xmlApi < automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > >::parseTransition ( ext::deque < sax::Token >::iterator & input, automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & automaton ) { + sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "transition" ); + StateType from = automaton::AutomatonFromXMLParser::parseTransitionFrom < StateType > ( input ); + ext::variant < EpsilonType, SymbolType > inputVariant = automaton::AutomatonFromXMLParser::parseTransitionInputEpsilonSymbol < EpsilonType, SymbolType > ( input ); + StateType to = automaton::AutomatonFromXMLParser::parseTransitionTo < StateType > ( input ); + sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, "transition" ); + + automaton.addTransition ( std::move ( from ), std::move ( inputVariant ), std::move ( to ) ); +} + +template < class SymbolType, class EpsilonType, class StateType > +void xmlApi < automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > >::compose ( ext::deque < sax::Token > & out, const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & automaton ) { + out.emplace_back ( xmlTagName ( ), sax::Token::TokenType::START_ELEMENT ); + + automaton::AutomatonToXMLComposer::composeStates ( out, automaton.getStates ( ) ); + automaton::AutomatonToXMLComposer::composeInputAlphabet ( out, automaton.getInputAlphabet ( ) ); + automaton::AutomatonToXMLComposer::composeInitialStates ( out, automaton.getInitialStates ( ) ); + automaton::AutomatonToXMLComposer::composeFinalStates ( out, automaton.getFinalStates ( ) ); + composeTransitions ( out, automaton ); + + out.emplace_back ( xmlTagName ( ), sax::Token::TokenType::END_ELEMENT ); +} + +template < class SymbolType, class EpsilonType, class StateType > +void xmlApi < automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > >::composeTransitions ( ext::deque < sax::Token > & out, const automaton::MultiInitialStateEpsilonNFA < SymbolType, EpsilonType, StateType > & automaton ) { + out.emplace_back ( "transitions", sax::Token::TokenType::START_ELEMENT ); + + for ( const auto & transition : automaton.getTransitions ( ) ) + for ( const auto & targetState : transition.second ) { + out.emplace_back ( "transition", sax::Token::TokenType::START_ELEMENT ); + + automaton::AutomatonToXMLComposer::composeTransitionFrom ( out, transition.first.first ); + automaton::AutomatonToXMLComposer::composeTransitionInputEpsilonSymbol ( out, transition.first.second ); + automaton::AutomatonToXMLComposer::composeTransitionTo ( out, targetState ); + + out.emplace_back ( "transition", sax::Token::TokenType::END_ELEMENT ); + } + + out.emplace_back ( "transitions", sax::Token::TokenType::END_ELEMENT ); +} + +} /* namespace core */ + +#endif /* _XML_MULTI_INITIAL_STATE_EPSILON_NFA_H_ */