diff --git a/alib2aux/src/convert/DotConverter.cpp b/alib2aux/src/convert/DotConverter.cpp index ca4862c8d20a7af35cf539753910f2a963e8c99c..aca2c3f1a9054f3c4d1ae21ce725924864823b82 100644 --- a/alib2aux/src/convert/DotConverter.cpp +++ b/alib2aux/src/convert/DotConverter.cpp @@ -18,6 +18,7 @@ auto DotConverterDFA = registration::AbstractRegister < convert::DotConverter, s auto DotConverterExtendedNFA = registration::AbstractRegister < convert::DotConverter, std::string, const automaton::ExtendedNFA < > & > ( convert::DotConverter::convert ); auto DotConverterCompactNFA = registration::AbstractRegister < convert::DotConverter, std::string, const automaton::CompactNFA < > & > ( convert::DotConverter::convert ); auto DotConverterNFTA = registration::AbstractRegister < convert::DotConverter, std::string, const automaton::NFTA < > & > ( convert::DotConverter::convert ); +auto DotConverterUnorderedNFTA = registration::AbstractRegister < convert::DotConverter, std::string, const automaton::UnorderedNFTA < > & > ( convert::DotConverter::convert ); auto DotConverterDFTA = registration::AbstractRegister < convert::DotConverter, std::string, const automaton::DFTA < > & > ( convert::DotConverter::convert ); auto DotConverterDPDA = registration::AbstractRegister < convert::DotConverter, std::string, const automaton::DPDA < > & > ( convert::DotConverter::convert ); auto DotConverterSinglePopDPDA = registration::AbstractRegister < convert::DotConverter, std::string, const automaton::SinglePopDPDA < > & > ( convert::DotConverter::convert ); diff --git a/alib2aux/src/convert/DotConverter.h b/alib2aux/src/convert/DotConverter.h index c465152896c0806ba6ef8b172fced31955ec7430..4312a54736f12e6eb311ef58b040fedf2cfc9622 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/UnorderedNFTA.h> #include <automaton/TA/ExtendedNFTA.h> #include <automaton/TA/DFTA.h> #include <automaton/PDA/NPDA.h> @@ -72,6 +73,9 @@ class DotConverter { template < class SymbolType, class StateType > static void transitions(const automaton::NFTA < SymbolType, StateType > & fta, const ext::map < StateType, int > & states, std::ostream & out); + template < class SymbolType, class StateType > + static void transitions(const automaton::UnorderedNFTA < SymbolType, StateType > & fta, const ext::map < StateType, int > & states, std::ostream & out); + template < class SymbolType, class StateType > static void transitions(const automaton::ExtendedNFTA < SymbolType, StateType > & fta, const ext::map < StateType, int > & states, std::ostream & out); @@ -132,6 +136,9 @@ public: template < class SymbolType, class StateType > static void convert(std::ostream& out, const automaton::NFTA < SymbolType, StateType > & a); + template < class SymbolType, class StateType > + static void convert(std::ostream& out, const automaton::UnorderedNFTA < SymbolType, StateType > & a); + template < class SymbolType, class StateType > static void convert(std::ostream& out, const automaton::ExtendedNFTA < SymbolType, StateType > & a); @@ -404,6 +411,34 @@ void DotConverter::convert(std::ostream& out, const automaton::NFTA < SymbolType out << "}"; } +template < class SymbolType, class StateType > +void DotConverter::convert(std::ostream& out, const automaton::UnorderedNFTA < SymbolType, StateType > & a) { + out << "digraph automaton {\n"; + out << "rankdir=LR;\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 ), "\"", "\\\"" ) << "\"]; " << 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.second << ";\n"; + } + } + + transitions(a, states, out); + out << "}"; +} + template < class SymbolType, class StateType > void DotConverter::convert(std::ostream& out, const automaton::ExtendedNFTA < SymbolType, StateType > & a) { out << "digraph automaton {\n"; @@ -1100,6 +1135,55 @@ void DotConverter::transitions(const automaton::NFTA < SymbolType, StateType > & } } +template < class SymbolType, class StateType > +void DotConverter::transitions(const automaton::UnorderedNFTA < SymbolType, StateType > & fta, const ext::map<StateType, int>& states, std::ostream& out) { + ext::map<std::pair<int, ext::vector<int>>, std::string> transitions; + + //put transitions from automaton to "transitions" + for (const auto& transition : fta.getTransitions()) { + std::string symbol = replace ( factory::StringDataFactory::toString ( transition.first.first.getSymbol( )), "\"", "\\\"" ); + symbol += ext::to_string(transition.first.first.getRank()); + + std::pair<int, ext::vector<int>> key(states.find(transition.second)->second, {}); + for(const StateType& state : transition.first.second) { + key.second.push_back(states.find(state)->second); + } + ext::map<std::pair<int, ext::vector<int>>, std::string>::iterator mapit = transitions.find(key); + + if (mapit == transitions.end()) { + transitions.insert(std::make_pair(key, symbol)); + } else { + mapit->second += ","; + + size_t pos = mapit->second.find_last_of("\n"); + if(pos == std::string::npos) pos = 0; + if(mapit->second.size() - pos > 100) mapit->second += "\n"; + else mapit->second += " "; + + mapit->second += symbol; + } + } + + //Print auxilary dots + for (unsigned i = 1; i <= transitions.size(); i++) { + out << "node [shape = point, label=\"\"]; " << states.size() + i << ";\n"; + } + + //print the map + unsigned i = states.size() + 1; + for (std::pair<const std::pair<int, ext::vector<int>>, std::string>& transition : transitions) { + out << i << " -> " << transition.first.first; + replaceInplace(transition.second, "\n", "\\n"); + out << "[label=\"" << transition.second << "\"]\n"; + unsigned j = 0; + for(int from : transition.first.second) { + out << from << " -> " << i << "\n"; + j++; + } + i++; + } +} + template < class SymbolType, class StateType > void DotConverter::transitions(const automaton::DFTA < SymbolType, StateType > & fta, const ext::map<StateType, int>& states, std::ostream& out) { ext::map<std::pair<int, ext::vector<int>>, std::string> transitions;