16
16
#include < cassert>
17
17
#include < functional>
18
18
#include < iosfwd>
19
+ #include < iostream>
19
20
#include < list>
20
21
#include < map>
21
22
#include < queue>
23
+ #include < sstream>
22
24
#include < stack>
23
25
#include < vector>
24
26
@@ -60,6 +62,39 @@ class graph_nodet
60
62
{
61
63
out.erase (n);
62
64
}
65
+
66
+ private:
67
+ // / \brief Node with attributes suitable for Graphviz DOT format
68
+ // /
69
+ // / Derived types may override this function to produce more informative DOT
70
+ // / diagrams than the default implementation, which displays only the node
71
+ // / index. The return value should be a list of node attributes within square
72
+ // / brackets that can be parsed by `dot`. Here is a sample implementation for
73
+ // / a fictional node type with `is_evil()` and `is_pink()` functions:
74
+ // /
75
+ // / std::stringstream ss;
76
+ // / ss << "[shape=\"" << is_evil() ? "box" : "diamond"
77
+ // / << "\", color=\"" << is_pink() ? "#e91e63" : "#9c27b0"
78
+ // / << "\", label=\"this is node " << std::to_string(idx)
79
+ // / << "\"]";
80
+ // / return ss.str();
81
+ // /
82
+ virtual std::string dot_attributes (node_indext idx) const
83
+ {
84
+ return " " ;
85
+ }
86
+
87
+ public:
88
+ std::string pretty (node_indext idx) const
89
+ {
90
+ std::stringstream ss;
91
+ ss << std::to_string (idx) << " " << dot_attributes (idx);
92
+ return ss.str ();
93
+ }
94
+
95
+ virtual ~graph_nodet ()
96
+ {
97
+ }
63
98
};
64
99
65
100
// / A node type with an extra bit
@@ -877,9 +912,11 @@ void output_dot_generic(
877
912
const std::function<
878
913
void(const node_index_type &, std::function<void (const node_index_type &)>)>
879
914
&for_each_succ,
880
- const std::function<std::string(const node_index_type &)> node_to_string)
915
+ const std::function<std::string(const node_index_type &)> node_to_string,
916
+ const std::function<std::string(const node_index_type &)> node_to_pretty)
881
917
{
882
918
for_each_node ([&](const node_index_type &i) {
919
+ out << node_to_pretty (i) << " ;\n " ;
883
920
for_each_succ (i, [&](const node_index_type &n) {
884
921
out << node_to_string (i) << " -> " << node_to_string (n) << ' \n ' ;
885
922
});
@@ -914,7 +951,7 @@ template <class N>
914
951
void grapht<N>::output_dot(std::ostream &out) const
915
952
{
916
953
const auto for_each_node =
917
- [& ](const std::function<void (const node_indext &)> &f) {
954
+ [this ](const std::function<void (const node_indext &)> &f) {
918
955
for (node_indext i = 0 ; i < nodes.size (); ++i)
919
956
f (i);
920
957
};
@@ -924,8 +961,14 @@ void grapht<N>::output_dot(std::ostream &out) const
924
961
for_each_successor (i, f);
925
962
};
926
963
927
- const auto to_string = [](const node_indext &i) { return std::to_string (i); };
928
- output_dot_generic<node_indext>(out, for_each_node, for_each_succ, to_string);
964
+ const auto to_string = [](const node_indext &i) {
965
+ return std::to_string (i);
966
+ };
967
+ const auto to_pretty_string = [this ](const node_indext &i) {
968
+ return nodes[i].pretty (i);
969
+ };
970
+ output_dot_generic<node_indext>(
971
+ out, for_each_node, for_each_succ, to_string, to_pretty_string);
929
972
}
930
973
931
974
#endif // CPROVER_UTIL_GRAPH_H
0 commit comments