Caffe2 - C++ API
A deep learning, cross platform ML framework
Dot.h
1 #ifndef NOM_CONVERTERS_DOT_H
2 #define NOM_CONVERTERS_DOT_H
3 
4 #include "nomnigraph/Graph/Graph.h"
5 #include "nomnigraph/Support/Casting.h"
6 
7 #include <functional>
8 #include <iostream>
9 #include <sstream>
10 
11 namespace {
12 
13 template <typename T, typename U = T> class DotGenerator {
14 public:
15  using NodePrinter = std::function<std::map<std::string, std::string>(
16  typename nom::Graph<T, U>::NodeRef)>;
17  using EdgePrinter = std::function<std::map<std::string, std::string>(
18  typename nom::Graph<T, U>::EdgeRef)>;
19 
20  static std::map<std::string, std::string>
21  defaultEdgePrinter(typename nom::Graph<T, U>::EdgeRef) {
22  std::map<std::string, std::string> labelMap;
23  return labelMap;
24  }
25 
26  DotGenerator(typename nom::Graph<T, U> *g) : g_(g) {}
27 
28  std::string convert(NodePrinter nodePrinter, EdgePrinter edgePrinter) {
29  std::ostringstream output;
30  output << "digraph G {\n\
31  bgcolor=\"#ffffff00\"\n\
32  color=white\n\
33  node[fontcolor=white,color=white];\n\
34  edge[fontcolor=white,color=white];\n\
35  ";
36  for (const auto &node : g_->getMutableNodes()) {
37  output << (uint64_t)node; // dot doesn't like hex
38  output << "[";
39  for (const auto &attrib : nodePrinter(node)) {
40  output << attrib.first << "=\"" << attrib.second << "\",";
41  }
42  output << "];\n";
43  for (const auto &edge : node->getOutEdges()) {
44  output << (uint64_t)edge->tail() << " -> " << (uint64_t)edge->head();
45  output << "[";
46  for (const auto &attrib : edgePrinter(edge)) {
47  output << attrib.first << "=\"" << attrib.second << "\",";
48  }
49  output << "];\n";
50  }
51  }
52  for (auto i = 0; i < subgraphs_.size(); ++i) {
53  const auto &subgraph = subgraphs_[i];
54  output << "subgraph cluster" << i << " {\n";
55  output << "style=dotted;\n";
56  for (const auto &node : subgraph->getNodes()) {
57  output << static_cast<uint64_t>(node);
58  output << ";\n";
59  }
60  output << "}\n";
61  }
62  output << "}";
63  return output.str();
64  }
65 
66  void addSubgraph(const nom::Subgraph<T, U> *s) { subgraphs_.emplace_back(s); }
67 
68 private:
69  typename nom::Graph<T, U> *g_;
70  typename std::vector<const nom::Subgraph<T, U> *> subgraphs_;
71 };
72 
73 } // namespace
74 
75 namespace nom {
76 namespace converters {
77 
78 template <typename T, typename U = T>
79 std::string
80 convertToDotString(nom::Graph<T, U> *g,
81  typename DotGenerator<T, U>::NodePrinter nodePrinter,
82  typename DotGenerator<T, U>::EdgePrinter edgePrinter =
83  DotGenerator<T, U>::defaultEdgePrinter) {
84  auto d = DotGenerator<T, U>(g);
85  return d.convert(nodePrinter, edgePrinter);
86 }
87 
88 template <typename T, typename U = T>
89 std::string
90 convertToDotString(nom::Graph<T, U> *g,
91  const std::vector<nom::Subgraph<T, U>> &subgraphs,
92  typename DotGenerator<T, U>::NodePrinter nodePrinter,
93  typename DotGenerator<T, U>::EdgePrinter edgePrinter =
94  DotGenerator<T, U>::defaultEdgePrinter) {
95  auto d = DotGenerator<T, U>(g);
96  for (const auto &subgraph : subgraphs) {
97  d.addSubgraph(&subgraph);
98  }
99  return d.convert(nodePrinter, edgePrinter);
100 }
101 
102 } // namespace converters
103 } // namespace nom
104 
105 #endif // NOM_CONVERTERS_DOT_H
Effectively a constant reference to a graph.
Definition: Graph.h:110
Definition: Caffe2.cc:16
A simple graph implementation.
Definition: Graph.h:30