Skip to content

Commit d706891

Browse files
Merge pull request #2913 from karkhaz/kk-graph-pretty-nodes
Subtypes of graph_nodet can override DOT output
2 parents 24a9ee3 + 37fc17f commit d706891

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
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: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Author: Daniel Kroening, [email protected]
1919
#include <list>
2020
#include <map>
2121
#include <queue>
22+
#include <sstream>
2223
#include <stack>
2324
#include <vector>
2425

@@ -60,6 +61,39 @@ class graph_nodet
6061
{
6162
out.erase(n);
6263
}
64+
65+
private:
66+
/// \brief Node with attributes suitable for Graphviz DOT format
67+
///
68+
/// Derived types may override this function to produce more informative DOT
69+
/// diagrams than the default implementation, which displays only the node
70+
/// index. The return value should be a list of node attributes within square
71+
/// brackets that can be parsed by `dot`. Here is a sample implementation for
72+
/// a fictional node type with `is_evil()` and `is_pink()` functions:
73+
///
74+
/// std::stringstream ss;
75+
/// ss << "[shape=\"" << is_evil() ? "box" : "diamond"
76+
/// << "\", color=\"" << is_pink() ? "#e91e63" : "#9c27b0"
77+
/// << "\", label=\"this is node " << std::to_string(idx)
78+
/// << "\"]";
79+
/// return ss.str();
80+
///
81+
virtual std::string dot_attributes(const node_indext &idx) const
82+
{
83+
return "";
84+
}
85+
86+
public:
87+
std::string pretty(const node_indext &idx) const
88+
{
89+
std::stringstream ss;
90+
ss << std::to_string(idx) << " " << dot_attributes(idx);
91+
return ss.str();
92+
}
93+
94+
virtual ~graph_nodet()
95+
{
96+
}
6397
};
6498

6599
/// A node type with an extra bit
@@ -877,9 +911,11 @@ void output_dot_generic(
877911
const std::function<
878912
void(const node_index_type &, std::function<void(const node_index_type &)>)>
879913
&for_each_succ,
880-
const std::function<std::string(const node_index_type &)> node_to_string)
914+
const std::function<std::string(const node_index_type &)> node_to_string,
915+
const std::function<std::string(const node_index_type &)> node_to_pretty)
881916
{
882917
for_each_node([&](const node_index_type &i) {
918+
out << node_to_pretty(i) << ";\n";
883919
for_each_succ(i, [&](const node_index_type &n) {
884920
out << node_to_string(i) << " -> " << node_to_string(n) << '\n';
885921
});
@@ -914,7 +950,7 @@ template <class N>
914950
void grapht<N>::output_dot(std::ostream &out) const
915951
{
916952
const auto for_each_node =
917-
[&](const std::function<void(const node_indext &)> &f) {
953+
[this](const std::function<void(const node_indext &)> &f) {
918954
for(node_indext i = 0; i < nodes.size(); ++i)
919955
f(i);
920956
};
@@ -925,7 +961,11 @@ void grapht<N>::output_dot(std::ostream &out) const
925961
};
926962

927963
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_pretty_string = [this](const node_indext &i) {
965+
return nodes[i].pretty(i);
966+
};
967+
output_dot_generic<node_indext>(
968+
out, for_each_node, for_each_succ, to_string, to_pretty_string);
929969
}
930970

931971
#endif // CPROVER_UTIL_GRAPH_H

0 commit comments

Comments
 (0)