diff --git a/alib2algo/src/automaton/transform/AutomataUnion.cpp b/alib2algo/src/automaton/transform/AutomataUnion.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f743b2d8219ec45fd7fc9c3efdf0c1fefc06acc3 --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomataUnion.cpp @@ -0,0 +1,41 @@ +/* + * AutomataUnion.cpp + * + * Created on: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#include "AutomataUnion.h" +#include <registration/AlgoRegistration.hpp> + +namespace { + +auto AutomataUnionEpsilonNFA = registration::AbstractRegister < automaton::transform::AutomataUnion, automaton::MultiInitialStateEpsilonNFA < DefaultSymbolType, ext::pair < DefaultStateType, unsigned > >, const automaton::EpsilonNFA < > &, const automaton::EpsilonNFA < > & > ( automaton::transform::AutomataUnion::unification, "first", "second" ).setDocumentation ( +"Union of two automata using epsilon transitions.\n\ +\n\ +@param first First automaton (A1)\n\ +@param second Second automaton (A2)\n\ +@return multi initial state nondeterministic epsilon FA representing the union of two automata" ); + +auto AutomataUnionNFA = registration::AbstractRegister < automaton::transform::AutomataUnion, automaton::MultiInitialStateNFA < DefaultSymbolType, ext::pair < DefaultStateType, unsigned > >, const automaton::NFA < > &, const automaton::NFA < > & > ( automaton::transform::AutomataUnion::unification, "first", "second" ).setDocumentation ( +"Union of two automata using epsilon transitions.\n\ +\n\ +@param first First automaton (A1)\n\ +@param second Second automaton (A2)\n\ +@return multi initial state nondeterministic FA representing the union of two automata" ); + +auto AutomataUnionDFA = registration::AbstractRegister < automaton::transform::AutomataUnion, automaton::MultiInitialStateNFA < DefaultSymbolType, ext::pair < DefaultStateType, unsigned > >, const automaton::DFA < > &, const automaton::DFA < > & > ( automaton::transform::AutomataUnion::unification, "first", "second" ).setDocumentation ( +"Union of two automata using epsilon transitions.\n\ +\n\ +@param first First automaton (A1)\n\ +@param second Second automaton (A2)\n\ +@return multi initial state nondeterministic FA representing the union of two automata" ); + +auto AutomataUnionNFTA = registration::AbstractRegister < automaton::transform::AutomataUnion, automaton::NFTA < DefaultSymbolType, ext::pair < DefaultStateType, unsigned > >, const automaton::NFTA < > &, const automaton::NFTA < > & > ( automaton::transform::AutomataUnion::unification, "first", "second" ).setDocumentation ( +"Union of two finite tree automata.\n\ +\n\ +@param first First automaton (A1)\n\ +@param second Second automaton (A2)\n\ +@return nondeterministic FTA representing the union of two automata" ); + +} /* namespace */ diff --git a/alib2algo/src/automaton/transform/AutomataUnion.h b/alib2algo/src/automaton/transform/AutomataUnion.h new file mode 100644 index 0000000000000000000000000000000000000000..52140cee819f9f6326ec167cc4453d89fa9e99a3 --- /dev/null +++ b/alib2algo/src/automaton/transform/AutomataUnion.h @@ -0,0 +1,226 @@ +/* + * AutomataUnion.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: 20. 11. 2014 + * Author: Tomas Pecka + */ + +#ifndef AUTOMATA_UNION_H_ +#define AUTOMATA_UNION_H_ + +#include <automaton/FSM/MultiInitialStateEpsilonNFA.h> +#include <automaton/TA/NFTA.h> + +namespace automaton { + +namespace transform { + +/** + * Union of two finite automata. + * For finite automata A1, A2, we create a finite automaton A such that L(A) = L(A1) \cup L(A2). + * This method utilizes epsilon transitions in finite automata (Melichar: Jazyky a překlady, 2.73). + */ +class AutomataUnion { +public: + /** + * Union of two automata using epsilon transitions. + * @tparam SymbolType Type for input symbols. + * @tparam StateType Type for states. + * @param first First automaton (A1) + * @param second Second automaton (A2) + * @return multi initial state epsilon nondeterministic FA representing the union of two automata + */ + template < class SymbolType, class StateType > + static automaton::MultiInitialStateEpsilonNFA < SymbolType, ext::pair < StateType, unsigned > > unification(const automaton::EpsilonNFA < SymbolType, StateType > & first, const automaton::EpsilonNFA < SymbolType, StateType > & second); + + /** + * @overload + * @return multi initial state nondeterministic FA representing the union of two automata + */ + template < class SymbolType, class StateType > + static automaton::MultiInitialStateNFA < SymbolType, ext::pair < StateType, unsigned > > unification(const automaton::NFA < SymbolType, StateType > & first, const automaton::NFA < SymbolType, StateType > & second); + + /** + * @overload + * @return multi initial state nondeterministic FA representing the union of two automata + */ + template < class SymbolType, class StateType > + static automaton::MultiInitialStateNFA < SymbolType, ext::pair < StateType, unsigned > > unification(const automaton::DFA < SymbolType, StateType > & first, const automaton::DFA < SymbolType, StateType > & second); + + /** + * Union of two finite tree automata. + * @tparam SymbolType Type for input symbols. + * @tparam StateType Type for states. + * @param first First automaton (A1) + * @param second Second automaton (A2) + * @return NFTA representing the union of two automata + */ + template < class SymbolType, class StateType > + static automaton::NFTA < SymbolType, ext::pair < StateType, unsigned > > unification ( const automaton::NFTA < SymbolType, StateType > & first, const automaton::NFTA < SymbolType, StateType > & second ); + +}; + +template < class SymbolType, class StateType > +automaton::MultiInitialStateEpsilonNFA < SymbolType, ext::pair < StateType, unsigned > > AutomataUnion::unification(const automaton::EpsilonNFA < SymbolType, StateType > & first, const automaton::EpsilonNFA < SymbolType, StateType > & second) { + unsigned firstDefault = 1; + unsigned secondDefault = 2; + + automaton::MultiInitialStateEpsilonNFA < SymbolType, ext::pair < StateType, unsigned > > res; + + for(const auto& a : first.getInputAlphabet()) + res.addInputSymbol(a); + for(const auto& a : second.getInputAlphabet()) + res.addInputSymbol(a); + + for ( const auto & q : first.getStates ( ) ) + res.addState ( ext::make_pair ( q, firstDefault ) ); + for ( const auto & q : second.getStates ( ) ) + res.addState ( ext::make_pair ( q, secondDefault ) ); + + for(const auto& q : first.getFinalStates()) + res.addFinalState ( ext::make_pair ( q, firstDefault ) ); + for(const auto& q : second.getFinalStates()) + res.addFinalState ( ext::make_pair ( q, secondDefault ) ); + + res.addInitialState ( ext::make_pair ( first.getInitialState ( ), firstDefault ) ); + res.addInitialState ( ext::make_pair ( second.getInitialState ( ), secondDefault ) ); + + for(const auto& t : first.getTransitions()) + res.addTransition ( ext::make_pair ( t.first.first, firstDefault ), t.first.second, ext::make_pair ( t.second, firstDefault ) ); + + for(const auto& t : second.getTransitions()) + res.addTransition ( ext::make_pair ( t.first.first, secondDefault ), t.first.second, ext::make_pair ( t.second, secondDefault ) ); + + return res; +} + +template < class SymbolType, class StateType > +automaton::MultiInitialStateNFA < SymbolType, ext::pair < StateType, unsigned > > AutomataUnion::unification(const automaton::NFA < SymbolType, StateType > & first, const automaton::NFA < SymbolType, StateType > & second) { + unsigned firstDefault = 1; + unsigned secondDefault = 2; + + automaton::MultiInitialStateNFA < SymbolType, ext::pair < StateType, unsigned > > res; + + for(const auto& a : first.getInputAlphabet()) + res.addInputSymbol(a); + for(const auto& a : second.getInputAlphabet()) + res.addInputSymbol(a); + + for ( const auto & q : first.getStates ( ) ) + res.addState ( ext::make_pair ( q, firstDefault ) ); + for ( const auto & q : second.getStates ( ) ) + res.addState ( ext::make_pair ( q, secondDefault ) ); + + for(const auto& q : first.getFinalStates()) + res.addFinalState ( ext::make_pair ( q, firstDefault ) ); + for(const auto& q : second.getFinalStates()) + res.addFinalState ( ext::make_pair ( q, secondDefault ) ); + + res.addInitialState ( ext::make_pair ( first.getInitialState ( ), firstDefault ) ); + res.addInitialState ( ext::make_pair ( second.getInitialState ( ), secondDefault ) ); + + for(const auto& t : first.getTransitions()) + res.addTransition ( ext::make_pair ( t.first.first, firstDefault ), t.first.second, ext::make_pair ( t.second, firstDefault ) ); + + for(const auto& t : second.getTransitions()) + res.addTransition ( ext::make_pair ( t.first.first, secondDefault ), t.first.second, ext::make_pair ( t.second, secondDefault ) ); + + return res; +} + +template < class SymbolType, class StateType > +automaton::MultiInitialStateNFA < SymbolType, ext::pair < StateType, unsigned > > AutomataUnion::unification(const automaton::DFA< SymbolType, StateType > & first, const automaton::DFA < SymbolType, StateType > & second) { + unsigned firstDefault = 1; + unsigned secondDefault = 2; + + automaton::MultiInitialStateNFA < SymbolType, ext::pair < StateType, unsigned > > res; + + for(const auto& a : first.getInputAlphabet()) + res.addInputSymbol(a); + for(const auto& a : second.getInputAlphabet()) + res.addInputSymbol(a); + + for ( const auto & q : first.getStates ( ) ) + res.addState ( ext::make_pair ( q, firstDefault ) ); + for ( const auto & q : second.getStates ( ) ) + res.addState ( ext::make_pair ( q, secondDefault ) ); + + for(const auto& q : first.getFinalStates()) + res.addFinalState ( ext::make_pair ( q, firstDefault ) ); + for(const auto& q : second.getFinalStates()) + res.addFinalState ( ext::make_pair ( q, secondDefault ) ); + + res.addInitialState ( ext::make_pair ( first.getInitialState ( ), firstDefault ) ); + res.addInitialState ( ext::make_pair ( second.getInitialState ( ), secondDefault ) ); + + for(const auto& t : first.getTransitions()) + res.addTransition ( ext::make_pair ( t.first.first, firstDefault ), t.first.second, ext::make_pair ( t.second, firstDefault ) ); + + for(const auto& t : second.getTransitions()) + res.addTransition ( ext::make_pair ( t.first.first, secondDefault ), t.first.second, ext::make_pair ( t.second, secondDefault ) ); + + return res; +} + +template < class SymbolType, class StateType > +automaton::NFTA < SymbolType, ext::pair < StateType, unsigned > > AutomataUnion::unification ( const automaton::NFTA < SymbolType, StateType > & first, const automaton::NFTA < SymbolType, StateType > & second ) { + unsigned firstDefault = 1; + unsigned secondDefault = 2; + + automaton::NFTA < SymbolType, ext::pair < StateType, unsigned > > res; + + for(const auto& a : first.getInputAlphabet()) + res.addInputSymbol(a); + for(const auto& a : second.getInputAlphabet()) + res.addInputSymbol(a); + + for ( const auto & q : first.getStates ( ) ) + res.addState ( ext::make_pair ( q, firstDefault ) ); + for ( const auto & q : second.getStates ( ) ) + res.addState ( ext::make_pair ( q, secondDefault ) ); + + for(const auto& q : first.getFinalStates()) + res.addFinalState ( ext::make_pair ( q, firstDefault ) ); + for(const auto& q : second.getFinalStates()) + res.addFinalState ( ext::make_pair ( q, secondDefault ) ); + + for(const auto& t : first.getTransitions()) { + ext::vector < ext::pair < StateType, unsigned > > source; + for ( const auto & state : t.first.second ) { + source.push_back ( ext::make_pair ( state, firstDefault ) ); + } + res.addTransition ( t.first.first, std::move ( source ), ext::make_pair ( t.second, firstDefault ) ); + } + + for(const auto& t : second.getTransitions()) { + ext::vector < ext::pair < StateType, unsigned > > source; + for ( const auto & state : t.first.second ) { + source.push_back ( ext::make_pair ( state, firstDefault ) ); + } + res.addTransition ( t.first.first, std::move ( source ), ext::make_pair ( t.second, secondDefault ) ); + } + + return res; +} + +} /* namespace transform */ + +} /* namespace automaton */ + +#endif /* AUTOMATA_UNION_H_ */