From 035553d984b03b8f9e58643657aef6202168caac Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Tue, 26 Mar 2019 19:19:02 +0100 Subject: [PATCH] some auxiliary algorithms needed by CompactDFA --- .../src/automaton/simplify/Normalize.cpp | 13 +++- alib2algo/src/automaton/simplify/Normalize.h | 62 ++++++++++++++++++- alib2aux/src/compare/AutomatonCompare.cpp | 1 + alib2aux/src/compare/AutomatonCompare.h | 13 ++++ alib2aux/src/compare/AutomatonDiff.cpp | 1 + alib2aux/src/compare/AutomatonDiff.h | 41 ++++++++++++ 6 files changed, 128 insertions(+), 3 deletions(-) diff --git a/alib2algo/src/automaton/simplify/Normalize.cpp b/alib2algo/src/automaton/simplify/Normalize.cpp index a24dfce767..30d0ba345f 100644 --- a/alib2algo/src/automaton/simplify/Normalize.cpp +++ b/alib2algo/src/automaton/simplify/Normalize.cpp @@ -16,17 +16,26 @@ auto NormalizeDFA = registration::AbstractRegister < Normalize, automaton::DFA < "Normalization of deterministic finite automata.\n\ The process of normalization is a BFS traversal through the graph representing the automaton. The states are named by integers in the visited order.\n\ \n\ -@param dfa determinsitic finite automaton to normalize\n\ +@param automaton determinsitic finite automaton to normalize\n\ @return @p dfa with state labels normalized\n\ \n\ @throws exception::CommonException if the passed dfa was not minimal connected dfa" ); +auto NormalizeCompactDFA = registration::AbstractRegister < Normalize, automaton::CompactDFA < DefaultSymbolType, unsigned >, const automaton::CompactDFA < > & > ( Normalize::normalize, "automaton" ).setDocumentation ( +"Normalization of compact deterministic finite automata.\n\ +The process of normalization is a BFS traversal through the graph representing the automaton. The states are named by integers in the visited order.\n\ +\n\ +@param automaton compact determinsitic finite automaton to normalize\n\ +@return @p compact dfa with state labels normalized\n\ +\n\ +@throws exception::CommonException if the passed compact dfa was not minimal connected dfa" ); + auto NormalizeDPDA = registration::AbstractRegister < Normalize, automaton::DPDA < DefaultSymbolType, DefaultEpsilonType, unsigned, unsigned >, const automaton::DPDA < > & > ( Normalize::normalize, "automaton" ).setDocumentation ( "Normalization of deterministic pushdown automata.\n\ The process of normalization of states is a BFS traversal through the graph representing the automaton. The states are named by integers in the visited order.\n\ We normalize also the pushdown store symbols.\n\ \n\ -@param dpda determinsitic pushdown automaton to normalize\n\ +@param automaton determinsitic pushdown automaton to normalize\n\ @return @p dpda with state labels normalized\n\ \n\ @throws exception::CommonException if the passed dpda was not deterministic connected pda" ); diff --git a/alib2algo/src/automaton/simplify/Normalize.h b/alib2algo/src/automaton/simplify/Normalize.h index 1227a42157..2ecf1131fb 100644 --- a/alib2algo/src/automaton/simplify/Normalize.h +++ b/alib2algo/src/automaton/simplify/Normalize.h @@ -25,6 +25,7 @@ #define NORMALIZE_H_ #include <automaton/FSM/DFA.h> +#include <automaton/FSM/CompactDFA.h> #include <automaton/PDA/DPDA.h> namespace automaton { @@ -55,6 +56,20 @@ public: template < class SymbolType, class StateType > static automaton::DFA < SymbolType, unsigned > normalize(const automaton::DFA < SymbolType, StateType > & dfa); + /** + * Normalization of compact deterministic finite automata. + * The process of normalization is a BFS traversal through the graph representing the automaton. The states are named by integers in the visited order. + * + * @tparam SymbolType Type for input symbols. + * @tparam StateType Type for states. + * @param dfa compact determinsitic finite automaton to normalize + * @return @p compact dfa with state labels normalized + * + * @throws exception::CommonException if the passed dfa was not minimal connected dfa + */ + template < class SymbolType, class StateType > + static automaton::CompactDFA < SymbolType, unsigned > normalize ( const automaton::CompactDFA < SymbolType, StateType > & dfa ); + /** * Normalization of deterministic pushdown automata. * The process of normalization of states is a BFS traversal through the graph representing the automaton. The states are named by integers in the visited order. @@ -118,6 +133,51 @@ automaton::DFA < SymbolType, unsigned > Normalize::normalize(const automaton::DF return result; } +template < class SymbolType, class StateType > +automaton::CompactDFA < SymbolType, unsigned > Normalize::normalize ( const automaton::CompactDFA < SymbolType, StateType > & fsm ) { + unsigned counter = 0; + ext::map < StateType, unsigned > normalizationData; + ext::deque < StateType > processingData; + + normalizationData.insert ( std::make_pair ( fsm.getInitialState ( ), counter ++ ) ); + processingData.push_back ( fsm.getInitialState ( ) ); + + while ( ! processingData.empty ( ) ) { + StateType current = std::move ( processingData.front ( ) ); + processingData.pop_front ( ); + + // Transitions are trivialy sorted by input sequence (from state is the same) + for ( const std::pair < const std::pair < StateType, ext::vector < SymbolType > >, StateType > & transition : fsm.getTransitionsFromState ( current ) ) { + if ( normalizationData.find ( transition.second ) == normalizationData.end ( ) ) { + normalizationData.insert ( std::make_pair ( transition.second, counter ++ ) ); + processingData.push_back ( transition.second ); + } + } + } + + if ( normalizationData.size ( ) != fsm.getStates ( ).size ( ) ) { + throw exception::CommonException ( "Automaton normalize require minimal deterministic finite automaton" ); + } + + automaton::CompactDFA < SymbolType, unsigned > result ( normalizationData.find ( fsm.getInitialState ( ) )->second ); + + result.setInputAlphabet ( fsm.getInputAlphabet ( ) ); + + for ( const StateType & state : fsm.getStates ( ) ) { + result.addState ( normalizationData.find ( state )->second ); + } + + for ( const StateType & finalState : fsm.getFinalStates ( ) ) { + result.addFinalState( normalizationData.find ( finalState )->second ); + } + + for ( const std::pair < const std::pair < StateType, ext::vector < SymbolType > >, StateType > & transition : fsm.getTransitions ( ) ) { + result.addTransition ( normalizationData.find ( transition.first.first )->second, transition.first.second, normalizationData.find ( transition.second )->second ); + } + + return result; +} + template < class InputSymbolType, class EpsilonType, class PushdownStoreSymbolType, class StateType > automaton::DPDA < InputSymbolType, EpsilonType, unsigned, unsigned > Normalize::normalize(const automaton::DPDA < InputSymbolType, EpsilonType, PushdownStoreSymbolType, StateType > & pda) { unsigned counterState = 0; @@ -146,7 +206,7 @@ automaton::DPDA < InputSymbolType, EpsilonType, unsigned, unsigned > Normalize:: transformedSymbols.push_back(normalizationDataSymbol.find(symbol)->second); } - // then first order is by input symbol and the second is this vector transfomed symbols + // then first order is by input symbol and the second is this vector transfomed symbols transform.insert(std::make_pair(std::make_pair(std::get<1>(iter.first), transformedSymbols), iter.second)); } else { stateFinished = false; diff --git a/alib2aux/src/compare/AutomatonCompare.cpp b/alib2aux/src/compare/AutomatonCompare.cpp index e9e2966e7c..e2d9949c70 100644 --- a/alib2aux/src/compare/AutomatonCompare.cpp +++ b/alib2aux/src/compare/AutomatonCompare.cpp @@ -15,6 +15,7 @@ auto AutomatonCompareNFA = registration::AbstractRegister < AutomatonCompare, bo auto AutomatonCompareMultiInitialStateNFA = registration::AbstractRegister < AutomatonCompare, bool, const automaton::MultiInitialStateNFA < > &, const automaton::MultiInitialStateNFA < > & > ( AutomatonCompare::compare ); auto AutomatonCompareEpsilonNFA = registration::AbstractRegister < AutomatonCompare, bool, const automaton::EpsilonNFA < > &, const automaton::EpsilonNFA < > & > ( AutomatonCompare::compare ); auto AutomatonCompareExtendedNFA = registration::AbstractRegister < AutomatonCompare, bool, const automaton::ExtendedNFA < > &, const automaton::ExtendedNFA < > & > ( AutomatonCompare::compare ); +auto AutomatonCompareCompactDFA = registration::AbstractRegister < AutomatonCompare, bool, const automaton::CompactDFA < > &, const automaton::CompactDFA < > & > ( AutomatonCompare::compare ); auto AutomatonCompareCompactNFA = registration::AbstractRegister < AutomatonCompare, bool, const automaton::CompactNFA < > &, const automaton::CompactNFA < > & > ( AutomatonCompare::compare ); auto AutomatonCompareDFTA = registration::AbstractRegister < AutomatonCompare, bool, const automaton::DFTA < > &, const automaton::DFTA < > & > ( AutomatonCompare::compare ); diff --git a/alib2aux/src/compare/AutomatonCompare.h b/alib2aux/src/compare/AutomatonCompare.h index fba02902ee..6c051982b5 100644 --- a/alib2aux/src/compare/AutomatonCompare.h +++ b/alib2aux/src/compare/AutomatonCompare.h @@ -14,6 +14,7 @@ #include "automaton/FSM/EpsilonNFA.h" #include "automaton/FSM/ExtendedNFA.h" #include "automaton/FSM/CompactNFA.h" +#include "automaton/FSM/CompactDFA.h" #include "automaton/TA/DFTA.h" #include "automaton/TA/NFTA.h" #include "automaton/PDA/NPDA.h" @@ -47,6 +48,9 @@ public: template<class SymbolType, class StateType> static bool compare(const automaton::ExtendedNFA < SymbolType, StateType > & a, const automaton::ExtendedNFA < SymbolType, StateType > & b); + template<class SymbolType, class StateType> + static bool compare(const automaton::CompactDFA < SymbolType, StateType > & a, const automaton::CompactDFA < SymbolType, StateType > & b); + template<class SymbolType, class StateType> static bool compare(const automaton::CompactNFA < SymbolType, StateType > & a, const automaton::CompactNFA < SymbolType, StateType > & b); @@ -135,6 +139,15 @@ bool AutomatonCompare::compare(const automaton::ExtendedNFA < SymbolType, StateT a.getTransitions() == b.getTransitions() ; } +template<class SymbolType, class StateType> +bool AutomatonCompare::compare(const automaton::CompactDFA < SymbolType, StateType > & a, const automaton::CompactDFA < SymbolType, StateType > & b) { + return a.getFinalStates() == b.getFinalStates() && + a.getInitialState() == b.getInitialState() && +// a.getInputAlphabet() == b.getInputAlphabet() && + a.getStates() == b.getStates() && + a.getTransitions() == b.getTransitions() ; +} + template<class SymbolType, class StateType> bool AutomatonCompare::compare(const automaton::CompactNFA < SymbolType, StateType > & a, const automaton::CompactNFA < SymbolType, StateType > & b) { return a.getFinalStates() == b.getFinalStates() && diff --git a/alib2aux/src/compare/AutomatonDiff.cpp b/alib2aux/src/compare/AutomatonDiff.cpp index a39388c13c..75ac9edca0 100644 --- a/alib2aux/src/compare/AutomatonDiff.cpp +++ b/alib2aux/src/compare/AutomatonDiff.cpp @@ -15,6 +15,7 @@ auto AutomatonDiffNFA = registration::AbstractRegister < AutomatonDiff, std::str auto AutomatonDiffMultiInitialStateNFA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::MultiInitialStateNFA < > &, const automaton::MultiInitialStateNFA < > & > ( AutomatonDiff::diff ); auto AutomatonDiffEpsilonNFA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::EpsilonNFA < > &, const automaton::EpsilonNFA < > & > ( AutomatonDiff::diff ); auto AutomatonDiffExtendedNFA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::ExtendedNFA < > &, const automaton::ExtendedNFA < > & > ( AutomatonDiff::diff ); +auto AutomatonDiffCompactDFA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::CompactDFA < > &, const automaton::CompactDFA < > & > ( AutomatonDiff::diff ); auto AutomatonDiffCompactNFA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::CompactNFA < > &, const automaton::CompactNFA < > & > ( AutomatonDiff::diff ); auto AutomatonDiffDFTA = registration::AbstractRegister < AutomatonDiff, std::string, const automaton::DFTA < > &, const automaton::DFTA < > & > ( AutomatonDiff::diff ); diff --git a/alib2aux/src/compare/AutomatonDiff.h b/alib2aux/src/compare/AutomatonDiff.h index fbe277211c..dc09c7ec4a 100644 --- a/alib2aux/src/compare/AutomatonDiff.h +++ b/alib2aux/src/compare/AutomatonDiff.h @@ -24,6 +24,7 @@ #include "automaton/FSM/MultiInitialStateNFA.h" #include "automaton/FSM/EpsilonNFA.h" #include "automaton/FSM/ExtendedNFA.h" +#include "automaton/FSM/CompactDFA.h" #include "automaton/FSM/CompactNFA.h" #include "automaton/TA/DFTA.h" #include "automaton/TA/NFTA.h" @@ -58,6 +59,9 @@ private: template<class SymbolType, class StateType> static void printDiff(const automaton::ExtendedNFA < SymbolType, StateType > & a, const automaton::ExtendedNFA < SymbolType, StateType > & b, std::ostream & out ); + template<class SymbolType, class StateType> + static void printDiff(const automaton::CompactDFA < SymbolType, StateType > & a, const automaton::CompactDFA < SymbolType, StateType > & b, std::ostream & out ); + template<class SymbolType, class StateType> static void printDiff(const automaton::CompactNFA < SymbolType, StateType > & a, const automaton::CompactNFA < SymbolType, StateType > & b, std::ostream & out ); @@ -253,6 +257,43 @@ void AutomatonDiff::printDiff(const automaton::EpsilonNFA < SymbolType, EpsilonT } } +template<class SymbolType, class StateType> +void AutomatonDiff::printDiff(const automaton::CompactDFA < SymbolType, StateType > & a, const automaton::CompactDFA < SymbolType, StateType > & b, std::ostream & out ) { + out << "AutomataComparer" << std::endl; + + if(a.getFinalStates() != b.getFinalStates()){ + out << "FinalStates" << std::endl; + + DiffAux::setDiff ( out, a.getFinalStates(), b.getFinalStates()); + } + + if(a.getInitialState() != b.getInitialState()) { + out << "Initial state" << std::endl; + + out << "< " << a.getInitialState() << std::endl; + out << "---" << std::endl; + out << "> " << b.getInitialState() << std::endl; + } + + if(a.getInputAlphabet() != b.getInputAlphabet()) { + out << "InputAlphabet" << std::endl; + + DiffAux::setDiff ( out, a.getInputAlphabet(), b.getInputAlphabet()); + } + + if(a.getStates() != b.getStates()) { + out << "States" << std::endl; + + DiffAux::setDiff ( out, a.getStates(), b.getStates()); + } + + if(a.getTransitions() != b.getTransitions()) { + out << "Transitions" << std::endl; + + DiffAux::mapDiff ( out, a.getTransitions(), b.getTransitions()); + } +} + template<class SymbolType, class StateType> void AutomatonDiff::printDiff(const automaton::ExtendedNFA < SymbolType, StateType > & a, const automaton::ExtendedNFA < SymbolType, StateType > & b, std::ostream & out ) { out << "AutomataComparer" << std::endl; -- GitLab