Skip to main content

GraphPrinter.h File

STL-only pretty printers for hybrid graphs. More...

Included Headers

#include "graph/Graph.h" #include <cstddef> #include <memory> #include <sstream> #include <string> #include <utility> #include <vector>

Namespaces Index

namespacesimaai
namespaceneat
namespacegraph

Classes Index

classGraphPrinter
structOptions

Description

STL-only pretty printers for hybrid graphs.

File Listing

The file content with the documentation metadata removed is:

1
6#pragma once
7
8#include "graph/Graph.h"
9
10#include <cstddef>
11#include <memory>
12#include <sstream>
13#include <string>
14#include <utility>
15#include <vector>
16
17namespace simaai::neat::graph {
18
19class GraphPrinter final {
20public:
21 struct Options {
22 bool show_index = true;
23 bool show_kind = true;
24 bool show_user_label = true;
25 bool show_backend = true;
26 bool show_ports = true;
27
28 std::size_t max_label_chars = 200;
29 std::size_t max_ports = 16;
30
31 bool dot_rankdir_lr = true;
32 std::string dot_graph_name = "sima_hybrid_graph";
33
34 bool mermaid_lr = true;
35 std::string mermaid_id_prefix = "n";
36 };
37
38 static std::string to_text(const Graph& g) {
39 return to_text(g, Options{});
40 }
41 static std::string to_text(const Graph& g, const Options& opt) {
42 std::ostringstream oss;
43 for (NodeId id = 0; id < g.node_count(); ++id) {
44 const auto& n = g.node(id);
45 if (!n)
46 continue;
47
48 if (opt.show_index)
49 oss << id << ") ";
50 if (opt.show_kind)
51 oss << n->kind();
52 if (opt.show_backend) {
53 oss << " [" << backend_name_(n->backend()) << "]";
54 }
55 if (opt.show_user_label) {
56 const std::string label = n->user_label();
57 if (!label.empty())
58 oss << " '" << truncate_(label, opt.max_label_chars) << "'";
59 }
60
61 if (opt.show_ports) {
62 oss << "\n in: " << join_ports_(n->input_ports(), opt.max_ports);
63 oss << "\n out: " << join_ports_(n->output_ports(), opt.max_ports);
64 }
65
66 if (id + 1 < g.node_count())
67 oss << "\n";
68 }
69 return oss.str();
70 }
71
72 static std::string to_dot(const Graph& g) {
73 return to_dot(g, Options{});
74 }
75 static std::string to_dot(const Graph& g, const Options& opt) {
76 std::ostringstream oss;
77 oss << "digraph " << dot_id_(opt.dot_graph_name) << " {\n";
78 if (opt.dot_rankdir_lr)
79 oss << " rankdir=LR;\n";
80 oss << " node [shape=box];\n";
81
82 for (NodeId id = 0; id < g.node_count(); ++id) {
83 const auto& n = g.node(id);
84 if (!n)
85 continue;
86
87 std::string label = node_label_(n, id, opt);
88 if (opt.show_ports) {
89 label += "\\n" + dot_escape_("in: " + join_ports_(n->input_ports(), opt.max_ports));
90 label += "\\n" + dot_escape_("out: " + join_ports_(n->output_ports(), opt.max_ports));
91 }
92
93 oss << " " << dot_node_id_(id) << " [label=\"" << dot_escape_(label) << "\"];\n";
94 }
95
96 for (const auto& e : g.edges()) {
97 const std::string label = g.port_name(e.from_port) + "->" + g.port_name(e.to_port);
98 oss << " " << dot_node_id_(e.from) << " -> " << dot_node_id_(e.to) << " [label=\""
99 << dot_escape_(label) << "\"];\n";
100 }
101
102 oss << "}\n";
103 return oss.str();
104 }
105
106 static std::string to_mermaid(const Graph& g) {
107 return to_mermaid(g, Options{});
108 }
109 static std::string to_mermaid(const Graph& g, const Options& opt) {
110 std::ostringstream oss;
111 oss << "flowchart " << (opt.mermaid_lr ? "LR" : "TD") << "\n";
112
113 for (NodeId id = 0; id < g.node_count(); ++id) {
114 const auto& n = g.node(id);
115 if (!n)
116 continue;
117
118 std::string label = node_label_(n, id, opt);
119 if (opt.show_ports) {
120 label += "\n" + ("in: " + join_ports_(n->input_ports(), opt.max_ports));
121 label += "\n" + ("out: " + join_ports_(n->output_ports(), opt.max_ports));
122 }
123
124 oss << " " << mermaid_node_id_(id, opt) << "[\"" << mermaid_escape_(label) << "\"]\n";
125 }
126
127 for (const auto& e : g.edges()) {
128 const std::string label = g.port_name(e.from_port) + "->" + g.port_name(e.to_port);
129 oss << " " << mermaid_node_id_(e.from, opt) << " -->|" << mermaid_escape_(label) << "| "
130 << mermaid_node_id_(e.to, opt) << "\n";
131 }
132
133 return oss.str();
134 }
135
136private:
137 static const char* backend_name_(Backend b) {
138 switch (b) {
140 return "pipeline";
141 case Backend::Stage:
142 return "stage";
143 }
144 return "unknown";
145 }
146
147 static std::string node_label_(const std::shared_ptr<Node>& n, std::size_t id,
148 const Options& opt) {
149 std::ostringstream oss;
150 if (opt.show_index)
151 oss << id << ") ";
152 if (opt.show_kind)
153 oss << n->kind();
154 if (opt.show_backend)
155 oss << " [" << backend_name_(n->backend()) << "]";
156 if (opt.show_user_label) {
157 const std::string label = n->user_label();
158 if (!label.empty())
159 oss << " '" << truncate_(label, opt.max_label_chars) << "'";
160 }
161 return oss.str();
162 }
163
164 static std::string join_ports_(const std::vector<PortDesc>& ports, std::size_t max_ports) {
165 if (ports.empty())
166 return "<none>";
167 std::ostringstream oss;
168 std::size_t count = 0;
169 for (const auto& p : ports) {
170 if (count++ > 0)
171 oss << ", ";
172 oss << p.name;
173 if (p.optional)
174 oss << "?";
175 if (count >= max_ports) {
176 if (ports.size() > max_ports)
177 oss << ", ...";
178 break;
179 }
180 }
181 return oss.str();
182 }
183
184 static std::string truncate_(const std::string& s, std::size_t max_len) {
185 if (s.size() <= max_len)
186 return s;
187 if (max_len < 3)
188 return s.substr(0, max_len);
189 return s.substr(0, max_len - 3) + "...";
190 }
191
192 static std::string dot_escape_(const std::string& s) {
193 std::string out;
194 out.reserve(s.size());
195 for (char c : s) {
196 if (c == '"')
197 out += "\\\"";
198 else if (c == '\\')
199 out += "\\\\";
200 else
201 out += c;
202 }
203 return out;
204 }
205
206 static std::string mermaid_escape_(const std::string& s) {
207 std::string out;
208 out.reserve(s.size());
209 for (char c : s) {
210 if (c == '"')
211 out += "\\\"";
212 else
213 out += c;
214 }
215 return out;
216 }
217
218 static std::string dot_id_(const std::string& s) {
219 if (s.empty())
220 return "graph";
221 return s;
222 }
223
224 static std::string dot_node_id_(std::size_t id) {
225 return "n" + std::to_string(id);
226 }
227
228 static std::string mermaid_node_id_(std::size_t id, const Options& opt) {
229 return opt.mermaid_id_prefix + std::to_string(id);
230 }
231};
232
233} // namespace simaai::neat::graph

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.9.1.