Skip to content

Commit 3e5d9b4

Browse files
committed
Subtypes of graph_nodet can override DOT output
This commit introduces a virtual pretty() method to graph_nodet, whose default implementation has the same behaviour as before (only outputting the node's graph index with no attributes when dumped to a Graphviz DOT file). Subtypes of graph_nodet can override this method to provide a more informative representation of themselves when grapht::output_dot() is called.
1 parent 2b5e925 commit 3e5d9b4

File tree

1 file changed

+45
-3
lines changed

1 file changed

+45
-3
lines changed

src/util/graph.h

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Author: Daniel Kroening, [email protected]
1616
#include <cassert>
1717
#include <functional>
1818
#include <iosfwd>
19+
#include <iostream>
1920
#include <list>
2021
#include <map>
2122
#include <queue>
@@ -60,6 +61,36 @@ class graph_nodet
6061
{
6162
out.erase(n);
6263
}
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+
}
6394
};
6495

6596
/// A node type with an extra bit
@@ -877,9 +908,14 @@ void output_dot_generic(
877908
const std::function<
878909
void(const node_index_type &, std::function<void(const node_index_type &)>)>
879910
&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)
881913
{
882914
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";
883919
for_each_succ(i, [&](const node_index_type &n) {
884920
out << node_to_string(i) << " -> " << node_to_string(n) << '\n';
885921
});
@@ -924,8 +960,14 @@ void grapht<N>::output_dot(std::ostream &out) const
924960
for_each_successor(i, f);
925961
};
926962

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);
929971
}
930972

931973
#endif // CPROVER_UTIL_GRAPH_H

0 commit comments

Comments
 (0)