Skip to content

Commit 324b68f

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 324b68f

File tree

2 files changed

+49
-5
lines changed

2 files changed

+49
-5
lines changed

src/solvers/refinement/string_refinement_util.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,8 @@ void string_dependenciest::output_dot(std::ostream &stream) const
497497
return ostream.str();
498498
};
499499
stream << "digraph dependencies {\n";
500-
output_dot_generic<nodet>(stream, for_each, for_each_succ, node_to_string);
500+
output_dot_generic<nodet>(
501+
stream, for_each, for_each_succ, node_to_string, node_to_string);
501502
stream << '}' << std::endl;
502503
}
503504

src/util/graph.h

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ 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>
23+
#include <sstream>
2224
#include <stack>
2325
#include <vector>
2426

@@ -60,6 +62,39 @@ class graph_nodet
6062
{
6163
out.erase(n);
6264
}
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+
}
6398
};
6499

65100
/// A node type with an extra bit
@@ -877,9 +912,11 @@ void output_dot_generic(
877912
const std::function<
878913
void(const node_index_type &, std::function<void(const node_index_type &)>)>
879914
&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)
881917
{
882918
for_each_node([&](const node_index_type &i) {
919+
out << node_to_pretty(i) << ";\n";
883920
for_each_succ(i, [&](const node_index_type &n) {
884921
out << node_to_string(i) << " -> " << node_to_string(n) << '\n';
885922
});
@@ -914,7 +951,7 @@ template <class N>
914951
void grapht<N>::output_dot(std::ostream &out) const
915952
{
916953
const auto for_each_node =
917-
[&](const std::function<void(const node_indext &)> &f) {
954+
[this](const std::function<void(const node_indext &)> &f) {
918955
for(node_indext i = 0; i < nodes.size(); ++i)
919956
f(i);
920957
};
@@ -924,8 +961,14 @@ void grapht<N>::output_dot(std::ostream &out) const
924961
for_each_successor(i, f);
925962
};
926963

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);
929972
}
930973

931974
#endif // CPROVER_UTIL_GRAPH_H

0 commit comments

Comments
 (0)