|
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>
|
@@ -60,6 +61,36 @@ class graph_nodet
|
60 | 61 | {
|
61 | 62 | out.erase(n);
|
62 | 63 | }
|
| 64 | + |
| 65 | + /// \brief Node with attributes suitable for Graphviz DOT format |
| 66 | + /// |
| 67 | + /// Derived types may override this function to produce more informative DOT |
| 68 | + /// diagrams than the default implementation, which displays only the node |
| 69 | + /// index. The return value should either be an empty string, or a single line |
| 70 | + /// representing this node that can be parsed by `dot`. This line would |
| 71 | + /// typically be the node index, followed by whitespace, followed by a list of |
| 72 | + /// node attributes within square brackets. Here is a sample implementation |
| 73 | + /// for a fictional node type with `is_evil()` and `is_pink()` functions: |
| 74 | + /// |
| 75 | + /// std::stringstream ss; |
| 76 | + /// ss << std::to_string(idx) |
| 77 | + /// << " [shape=\"" << is_evil() ? "box" : "diamond" |
| 78 | + /// << "\", color=\"" << is_pink() ? "#e91e63" : "#9c27b0" |
| 79 | + /// << "\", label=\"this is node " << std::to_string(idx) |
| 80 | + /// << "\"]"; |
| 81 | + /// return ss.str(); |
| 82 | + /// |
| 83 | + /// If this function returns an empty string for a particular node, |
| 84 | + /// grapht::output_dot() method will not output this node at all, nor any of |
| 85 | + /// its incoming or outgoing edges. |
| 86 | + virtual std::string pretty(node_indext idx) const |
| 87 | + { |
| 88 | + return std::to_string(idx); |
| 89 | + } |
| 90 | + |
| 91 | + virtual ~graph_nodet() |
| 92 | + { |
| 93 | + } |
63 | 94 | };
|
64 | 95 |
|
65 | 96 | /// A node type with an extra bit
|
@@ -877,9 +908,14 @@ void output_dot_generic(
|
877 | 908 | const std::function<
|
878 | 909 | void(const node_index_type &, std::function<void(const node_index_type &)>)>
|
879 | 910 | &for_each_succ,
|
880 |
| - const std::function<std::string(const node_index_type &)> node_to_string) |
| 911 | + const std::function<std::string(const node_index_type &)> node_to_string, |
| 912 | + const std::function<std::string(const node_index_type &)> node_to_pretty) |
881 | 913 | {
|
882 | 914 | for_each_node([&](const node_index_type &i) {
|
| 915 | + const std::string pretty = node_to_pretty(i); |
| 916 | + if(pretty == "") |
| 917 | + return; |
| 918 | + out << pretty << ";\n"; |
883 | 919 | for_each_succ(i, [&](const node_index_type &n) {
|
884 | 920 | out << node_to_string(i) << " -> " << node_to_string(n) << '\n';
|
885 | 921 | });
|
@@ -924,8 +960,14 @@ void grapht<N>::output_dot(std::ostream &out) const
|
924 | 960 | for_each_successor(i, f);
|
925 | 961 | };
|
926 | 962 |
|
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); |
| 963 | + const auto to_string = [&](const node_indext &i) { |
| 964 | + return std::to_string(i); |
| 965 | + }; |
| 966 | + const auto to_pretty_string = [&](const node_indext &i) { |
| 967 | + return nodes[i].pretty(i); |
| 968 | + }; |
| 969 | + output_dot_generic<node_indext>( |
| 970 | + out, for_each_node, for_each_succ, to_string, to_pretty_string); |
929 | 971 | }
|
930 | 972 |
|
931 | 973 | #endif // CPROVER_UTIL_GRAPH_H
|
0 commit comments