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