@@ -19,8 +19,7 @@ namespace reactor {
19
19
template <class E , class P > class Graph {
20
20
private:
21
21
std::map<E, std::vector<std::pair<P, E>>> graph_;
22
- std::size_t index{0 };
23
- std::map<E, std::string> name_map{};
22
+ std::set<E> nodes_{};
24
23
25
24
// custom compare operator this is required if u want special key values in std::map
26
25
// this is required for the Graph::get_edges() method
@@ -54,6 +53,8 @@ public:
54
53
55
54
// adds a single edge to the graph structure
56
55
void add_edge (E source, E destination, P properties) noexcept {
56
+ nodes_.insert (source);
57
+ nodes_.insert (destination);
57
58
if (graph_.find (source) == std::end (graph_)) {
58
59
Path edges{std::make_pair (properties, destination)};
59
60
graph_[source] = edges;
@@ -62,6 +63,8 @@ public:
62
63
}
63
64
}
64
65
66
+ auto get_nodes () -> std::set<E> { return nodes_; }
67
+
65
68
// this groups connections by same source and properties
66
69
[[nodiscard]] auto get_edges () const noexcept -> std::map<map_key, std::vector<E>, map_key_compare> {
67
70
std::map<map_key, std::vector<E>, map_key_compare> all_edges{};
@@ -89,39 +92,16 @@ public:
89
92
return keys;
90
93
}
91
94
92
- auto name_resolver (E object) -> std::string {
93
- char names[] = " ABCDEFGHIJKLMNOPQRSTUVGXYZabcdefghijklmnopqrstuvgxyz" ;
94
- if (name_map.find (object) == std::end (name_map)) {
95
- name_map[object] = names[index];
96
- index++;
97
- return std::string{names[index - 1 ], 1 };
98
- }
99
- return name_map[object];
100
- }
101
-
102
95
// the return type looks a little bit cursed what is happening here ?
103
96
// we have a map from the destination as a key to a list of paths through the graph.
104
97
// A path here is modelled by a list of edges (with properties and the next vertex).
105
98
auto naive_spanning_tree (E source) noexcept -> std::vector<std::vector<std::pair<P, E>>> {
106
- auto result = recursive_spanning_tree (source, std::vector<E>{});
107
-
108
- std::string mermaid_string = " graph TD;\n " ;
109
-
110
- for (auto path : result ) {
111
- mermaid_string += std::string (" " ) + name_resolver (source);
112
- for (auto edge : path) {
113
- mermaid_string += std::string (" -->" )+ name_resolver (edge.second );
114
- }
115
- mermaid_string += std::string (" ;\n " );
116
-
117
- }
118
- // std::cout << "EDGE: \n" << mermaid_string << std::endl;
119
- return result;
99
+ return recursive_spanning_tree (source, std::vector<E>{});
120
100
}
121
101
122
-
123
102
// this function goes recursively though the graph and tries to find every possible path
124
- auto recursive_spanning_tree (E source_node, std::vector<E> visited_nodes) -> std::vector<std::vector<std::pair<P, E>>> {
103
+ auto recursive_spanning_tree (E source_node, std::vector<E> visited_nodes)
104
+ -> std::vector<std::vector<std::pair<P, E>>> {
125
105
std::vector<Path> paths{};
126
106
127
107
if (graph_[source_node].empty ()) {
@@ -138,7 +118,7 @@ public:
138
118
auto temp_nodes = visited_nodes;
139
119
temp_nodes.push_back (current_node);
140
120
141
- for (auto path: recursive_spanning_tree (current_node, temp_nodes)) {
121
+ for (auto path : recursive_spanning_tree (current_node, temp_nodes)) {
142
122
path.insert (std::begin (path), child);
143
123
paths.push_back (path);
144
124
}
@@ -154,9 +134,8 @@ public:
154
134
auto spanning_tre = naive_spanning_tree (source);
155
135
std::vector<Path> relevant_paths{};
156
136
157
- std::copy_if (spanning_tre.begin (), spanning_tre.end (), std::back_inserter (relevant_paths), [destination](Path path) {
158
- return (*path.end ()).second == destination;
159
- });
137
+ std::copy_if (spanning_tre.begin (), spanning_tre.end (), std::back_inserter (relevant_paths),
138
+ [&, destination](Path path) { return path[path.size () - 1 ].second == destination; });
160
139
161
140
if (relevant_paths.empty ()) {
162
141
return std::nullopt;
@@ -185,12 +164,25 @@ public:
185
164
}
186
165
}
187
166
188
- auto to_mermaid () noexcept -> std::string {
167
+ auto to_mermaid () const noexcept -> std::string {
168
+ std::size_t index{0 };
169
+ std::map<E, std::string> name_map{};
189
170
std::string mermaid_string = " graph TD;\n " ;
190
171
172
+ auto name_resolver = [&](E object) -> std::string {
173
+ char names[] = " ABCDEFGHIJKLMNOPQRSTUVGXYZabcdefghijklmnopqrstuvgxyz" ;
174
+ if (name_map.find (object) == std::end (name_map)) {
175
+ name_map[object] = names[index];
176
+ index++;
177
+ return std::string{names[index - 1 ], 1 };
178
+ }
179
+ return name_map[object];
180
+ };
181
+
191
182
for (const auto & [source, destinations] : graph_) {
192
183
for (auto dest : destinations) {
193
- mermaid_string += std::string (" " ) + name_resolver (source) + std::string (" -->" ) + name_resolver (dest.second ) + std::string (" ;\n " );
184
+ mermaid_string += std::string (" " ) + name_resolver (source) + std::string (" -->" ) +
185
+ name_resolver (dest.second ) + std::string (" ;\n " );
194
186
}
195
187
}
196
188
return mermaid_string;
0 commit comments