From 1a9a52118b35219b9c68ed3aeba19672f7b041cd Mon Sep 17 00:00:00 2001
From: Tomas Pecka <peckato1@fit.cvut.cz>
Date: Thu, 21 Mar 2019 09:33:45 +0100
Subject: [PATCH] Aux: Simple DotConverter for RTEs and ExtendedNFTA

---
 alib2aux/src/convert/DotConverter.cpp        |   3 +
 alib2aux/src/convert/DotConverter.h          |  71 ++++++++++++
 alib2aux/src/convert/DotConverterRTEPart.hxx | 109 +++++++++++++++++++
 3 files changed, 183 insertions(+)
 create mode 100644 alib2aux/src/convert/DotConverterRTEPart.hxx

diff --git a/alib2aux/src/convert/DotConverter.cpp b/alib2aux/src/convert/DotConverter.cpp
index 51c3f7c9b0..9314f9b702 100644
--- a/alib2aux/src/convert/DotConverter.cpp
+++ b/alib2aux/src/convert/DotConverter.cpp
@@ -6,6 +6,7 @@
  */
 
 #include "DotConverter.h"
+#include "DotConverterRTEPart.hxx"
 #include <registration/AlgoRegistration.hpp>
 
 namespace convert {
@@ -29,5 +30,7 @@ auto DotConverterRealTimeHeightDeterministicNPDA = registration::AbstractRegiste
 auto DotConverterNPDA = registration::AbstractRegister < DotConverter, std::string, const automaton::NPDA < > & > ( DotConverter::convert );
 auto DotConverterSinglePopNPDA = registration::AbstractRegister < DotConverter, std::string, const automaton::SinglePopNPDA < > & > ( DotConverter::convert );
 auto DotConverterOneTapeDTM = registration::AbstractRegister < DotConverter, std::string, const automaton::OneTapeDTM < > & > ( DotConverter::convert );
+auto DotConverterExtendedNFTA = registration::AbstractRegister < DotConverter, std::string, const automaton::ExtendedNFTA < > & > ( DotConverter::convert );
+auto DotConverterFormalRTE = registration::AbstractRegister < DotConverter, std::string, const rte::FormalRTE < > & > ( DotConverter::convert );
 
 } /* namespace convert */
diff --git a/alib2aux/src/convert/DotConverter.h b/alib2aux/src/convert/DotConverter.h
index 77252e2acb..506deca5cd 100644
--- a/alib2aux/src/convert/DotConverter.h
+++ b/alib2aux/src/convert/DotConverter.h
@@ -26,6 +26,7 @@
 #include <automaton/FSM/ExtendedNFA.h>
 #include <automaton/FSM/CompactNFA.h>
 #include <automaton/TA/NFTA.h>
+#include <automaton/TA/ExtendedNFTA.h>
 #include <automaton/TA/DFTA.h>
 #include <automaton/PDA/NPDA.h>
 #include <automaton/PDA/SinglePopNPDA.h>
@@ -45,6 +46,8 @@
 #include <string/string/LinearString.h>
 #include <regexp/string/UnboundedRegExp.h>
 
+#include "DotConverterRTEPart.hxx"
+
 namespace convert {
 
 class DotConverter {
@@ -69,6 +72,9 @@ class DotConverter {
 	template < class SymbolType, class RankType, class StateType >
 	static void transitions(const automaton::NFTA < SymbolType, RankType, StateType > & fsm, const ext::map < StateType, int > & states, std::ostream & out);
 
+	template < class SymbolType, class RankType, class StateType >
+	static void transitions(const automaton::ExtendedNFTA < SymbolType, RankType, StateType > & fsm, const ext::map < StateType, int > & states, std::ostream & out);
+
 	template < class SymbolType, class RankType, class StateType >
 	static void transitions(const automaton::DFTA < SymbolType, RankType, StateType > & fsm, const ext::map < StateType, int > & states, std::ostream & out);
 
@@ -126,6 +132,9 @@ public:
 	template < class SymbolType, class RankType, class StateType >
 	static void convert(std::ostream& out, const automaton::NFTA < SymbolType, RankType, StateType > & a);
 
+	template < class SymbolType, class RankType, class StateType >
+	static void convert(std::ostream& out, const automaton::ExtendedNFTA < SymbolType, RankType, StateType > & a);
+
 	template < class SymbolType, class RankType, class StateType >
 	static void convert(std::ostream& out, const automaton::DFTA < SymbolType, RankType, StateType > & a);
 
@@ -162,6 +171,9 @@ public:
 	template < class SymbolType, class StateType >
 	static void convert(std::ostream& out, const automaton::OneTapeDTM < SymbolType, StateType > & a);
 
+	template < class SymbolType, class RankType >
+	static void convert(std::ostream& out, const rte::FormalRTE < SymbolType, RankType > & e );
+
 	template < class T >
 	static std::string convert ( const T & automaton ) {
 		std::stringstream ss;
@@ -392,6 +404,34 @@ void DotConverter::convert(std::ostream& out, const automaton::NFTA < SymbolType
 	out << "}";
 }
 
+template < class SymbolType, class RankType, class StateType >
+void DotConverter::convert(std::ostream& out, const automaton::ExtendedNFTA < SymbolType, RankType, StateType > & a) {
+	out << "digraph automaton {\n";
+	out << "rankdir=TD;\n";
+	int cnt = 1;
+
+	//Map states to indices
+	ext::map<StateType, int> states;
+	for (const StateType& state : a.getStates()) {
+		states.insert(std::make_pair(state, cnt++));
+	}
+
+	//Print final states
+	for (const StateType& state : a.getFinalStates()) {
+		out << "node [shape = doublecircle, label=\"" << replace ( factory::StringDataFactory::toString ( state ), "\"", "\\\"" ) << "\"]; State" << states.find(state)->second << ";\n";
+	}
+
+	//Print nonfinal states
+	for (const auto& state : states) {
+		if (!a.getFinalStates().count(state.first)) {
+			out << "node [shape = circle, label=\"" << replace ( factory::StringDataFactory::toString ( state.first ), "\"", "\\\"" ) << "\" ]; State" << state.second << ";\n";
+		}
+	}
+
+	transitions(a, states, out);
+	out << "}";
+}
+
 template < class SymbolType, class RankType, class StateType >
 void DotConverter::convert(std::ostream& out, const automaton::DFTA < SymbolType, RankType, StateType > & a) {
 	out << "digraph automaton {\n";
@@ -814,6 +854,13 @@ void DotConverter::transitions(const automaton::EpsilonNFA < SymbolType, Epsilon
 	}
 }
 
+template < class SymbolType, class RankType >
+void DotConverter::convert(std::ostream& out, const rte::FormalRTE < SymbolType, RankType > & e ) {
+	out << "digraph rte {\n";
+	out << DotConverterRTE::convertInternal ( e ) << '\n';
+	out << "}" << std::endl;
+}
+
 template < class SymbolType, class StateType >
 void DotConverter::transitions(const automaton::MultiInitialStateNFA < SymbolType, StateType >& fsm, const ext::map<StateType, int>& states, std::ostream& out) {
 	ext::map<std::pair<int, int>, std::string> transitions;
@@ -979,6 +1026,30 @@ void DotConverter::transitions(const automaton::CompactNFA < SymbolType, StateTy
 	}
 }
 
+template < class SymbolType, class RankType, class StateType >
+void DotConverter::transitions(const automaton::ExtendedNFTA < SymbolType, RankType, StateType > & fta, const ext::map<StateType, int>& states, std::ostream& out) {
+	//print the map
+	unsigned auxNodeCnt = 1;
+	for (const auto & transition : fta.getTransitions ( ) ) {
+		// print subgraph with the rte
+		out << '\n';
+		out << "subgraph cluster_rte_" << auxNodeCnt << "{" << '\n';
+		out << "label=\"rte_"  << auxNodeCnt << "\"\n";
+		out << "color = blue;\n";
+		out << convert::DotConverterRTE::convertInternal ( rte::FormalRTE < ext::variant < SymbolType, StateType >, RankType > ( transition.first.first ), "x" + ext::to_string ( auxNodeCnt ) + "x" );
+		out << "}\n" << std::endl;
+
+		out << "node [shape = point, label=\"\"]; Aux" << auxNodeCnt << ";\n";
+		unsigned j = 1;
+		for(const auto & state : transition.first.second) // from source states to connecting node
+			out << "State" << states.at ( state ) << " -> " << "Aux" << auxNodeCnt << "[label=\"" << j++ << "\"];\n";
+		for ( const auto & target : transition.second ) // from connecting node to target nodes
+			out << "Aux" << auxNodeCnt << " -> State" << states.at ( target ) << "[label=\"" << "rte_" << auxNodeCnt << "\"];\n";
+
+		auxNodeCnt++;
+	}
+}
+
 template < class SymbolType, class RankType, class StateType >
 void DotConverter::transitions(const automaton::NFTA < SymbolType, RankType, StateType > & fta, const ext::map<StateType, int>& states, std::ostream& out) {
 	ext::map<std::pair<int, ext::vector<int>>, std::string> transitions;
diff --git a/alib2aux/src/convert/DotConverterRTEPart.hxx b/alib2aux/src/convert/DotConverterRTEPart.hxx
new file mode 100644
index 0000000000..bea13a8472
--- /dev/null
+++ b/alib2aux/src/convert/DotConverterRTEPart.hxx
@@ -0,0 +1,109 @@
+/*
+ * DotConverterRTE.h
+ *
+ *  Created on: 15. 3. 2019
+ *	  Author: Tomas Pecka
+ */
+
+#ifndef DOT_CONVERTER_RTE_H
+#define DOT_CONVERTER_RTE_H
+
+#include <rte/formal/FormalRTE.h>
+#include <rte/formal/FormalRTEElements.h>
+
+namespace convert {
+
+class DotConverterRTE {
+public:
+	template < class SymbolType, class RankType >
+	static std::string convertInternal ( const rte::FormalRTE < SymbolType, RankType > & rte, const std::string & nodePrefix = "" );
+
+	template < class SymbolType, class RankType >
+	class Formal {
+	public:
+		static unsigned visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, std::stringstream & oss, unsigned & nodeIdCounter, const std::string & nodePrefix );
+		static unsigned visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, std::stringstream & oss, unsigned & nodeIdCounter, const std::string & nodePrefix );
+		static unsigned visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, std::stringstream & oss, unsigned & nodeIdCounter, const std::string & nodePrefix );
+		static unsigned visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, std::stringstream & oss, unsigned & nodeIdCounter, const std::string & nodePrefix );
+		static unsigned visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & node, std::stringstream & oss, unsigned & nodeIdCounter, const std::string & nodePrefix );
+		static unsigned visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & node, std::stringstream & oss, unsigned & nodeIdCounter, const std::string & nodePrefix );
+	};
+};
+
+template < class SymbolType, class RankType >
+std::string DotConverterRTE::convertInternal ( const rte::FormalRTE < SymbolType, RankType > & rte, const std::string & nodePrefix ) {
+	std::stringstream oss;
+	unsigned nodeIdCounter = 0;
+	rte.getRTE ( ).getStructure ( ).template accept < unsigned, DotConverterRTE::Formal < SymbolType, RankType > > ( oss, nodeIdCounter, nodePrefix );
+	return oss.str ( );
+}
+
+template < class SymbolType, class RankType >
+unsigned DotConverterRTE::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEAlternation < SymbolType, RankType > & node, std::stringstream & oss, unsigned & nodeIdCounter, const std::string & nodePrefix ) {
+	unsigned id = nodeIdCounter ++;
+
+	oss << nodePrefix << id << "[label=\"+\", shape=plaintext];" << std::endl;
+
+	size_t lId = node.getLeftElement  ( ).template accept < unsigned, DotConverterRTE::Formal < SymbolType, RankType > > ( oss, nodeIdCounter, nodePrefix );
+	size_t rId = node.getRightElement ( ).template accept < unsigned, DotConverterRTE::Formal < SymbolType, RankType > > ( oss, nodeIdCounter, nodePrefix );
+
+	oss << nodePrefix << id << " -> " << nodePrefix << lId << ";" << std::endl;
+	oss << nodePrefix << id << " -> " << nodePrefix << rId << ";" << std::endl;
+	return id;
+}
+
+template < class SymbolType, class RankType >
+unsigned DotConverterRTE::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESubstitution < SymbolType, RankType > & node, std::stringstream & oss, unsigned & nodeIdCounter, const std::string & nodePrefix ) {
+	unsigned id = nodeIdCounter ++;
+
+	oss << nodePrefix << id << "[label=\". " << node.getSubstitutionSymbol( ).getSymbol ( ).getSymbol ( ) << "\", shape=plaintext];" << std::endl;
+
+	size_t lId = node.getLeftElement  ( ).template accept < unsigned, DotConverterRTE::Formal < SymbolType, RankType > > ( oss, nodeIdCounter, nodePrefix );
+	size_t rId = node.getRightElement ( ).template accept < unsigned, DotConverterRTE::Formal < SymbolType, RankType > > ( oss, nodeIdCounter, nodePrefix );
+
+	oss << nodePrefix << id << " -> " << nodePrefix << lId << ";" << std::endl;
+	oss << nodePrefix << id << " -> " << nodePrefix << rId << ";" << std::endl;
+	return id;
+}
+
+template < class SymbolType, class RankType >
+unsigned DotConverterRTE::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEIteration < SymbolType, RankType > & node, std::stringstream & oss, unsigned & nodeIdCounter, const std::string & nodePrefix ) {
+	unsigned id = nodeIdCounter ++;
+
+	oss << nodePrefix << id << "[label=\"* " << node.getSubstitutionSymbol( ).getSymbol ( ).getSymbol ( ) << "\", shape=plaintext];" << std::endl;
+
+	unsigned childId = node.getElement ( ).template accept < unsigned, DotConverterRTE::Formal < SymbolType, RankType > > ( oss, nodeIdCounter, nodePrefix );
+
+	oss << nodePrefix << id << " -> " << nodePrefix << childId << ";" << std::endl;
+	return id;
+}
+
+template < class SymbolType, class RankType >
+unsigned DotConverterRTE::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESymbolAlphabet < SymbolType, RankType > & node, std::stringstream & oss, unsigned & nodeIdCounter, const std::string & nodePrefix ) {
+	unsigned id = nodeIdCounter ++;
+
+	oss << nodePrefix << id << "[label=\"" << node.getSymbol( ).getSymbol ( ) << "\", shape=plaintext];" << std::endl;
+
+	for ( const auto & child : node.getChildren ( ) ) {
+		unsigned childId = child.template accept < unsigned, DotConverterRTE::Formal < SymbolType, RankType > > ( oss, nodeIdCounter, nodePrefix );
+		oss << nodePrefix << id << " -> " << nodePrefix << childId << ";" << std::endl;
+	}
+
+	return id;
+}
+
+template < class SymbolType, class RankType >
+unsigned DotConverterRTE::Formal < SymbolType, RankType >::visit ( const rte::FormalRTESymbolSubst < SymbolType, RankType > & node, std::stringstream & oss, unsigned & nodeIdCounter, const std::string & nodePrefix ) {
+	oss << nodePrefix << nodeIdCounter << "[label=\"" << node.getSymbol ( ).getSymbol ( ) << "\", shape=plaintext];" << std::endl;
+	return nodeIdCounter ++;
+}
+
+template < class SymbolType, class RankType >
+unsigned DotConverterRTE::Formal < SymbolType, RankType >::visit ( const rte::FormalRTEEmpty < SymbolType, RankType > & , std::stringstream & oss, unsigned & nodeIdCounter, const std::string & nodePrefix ) {
+	oss << nodePrefix << nodeIdCounter << "[label=\"#0\", shape=plaintext];" << std::endl;
+	return nodeIdCounter ++;
+}
+
+} /* namespace convert */
+
+#endif /* DOT_CONVERTER_RTE_H */
-- 
GitLab