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