xrpld
Loading...
Searching...
No Matches
Digraph.h
1#pragma once
2
3#include <boost/container/flat_map.hpp>
4#include <boost/range/adaptor/transformed.hpp>
5#include <boost/range/iterator_range.hpp>
6
7#include <fstream>
8#include <optional>
9#include <type_traits>
10#include <unordered_map>
11
12namespace xrpl {
13namespace detail {
14// Dummy class when no edge data needed for graph
16{
17};
18
19} // namespace detail
20
21namespace test::csf {
22
33template <class Vertex, class EdgeData = detail::NoEdgeData>
35{
36 using Links = boost::container::flat_map<Vertex, EdgeData>;
37 using Graph = boost::container::flat_map<Vertex, Links>;
39
40 // Allows returning empty iterables for unknown vertices
42
43public:
52 bool
53 connect(Vertex source, Vertex target, EdgeData e)
54 {
55 return graph_[source].emplace(target, e).second;
56 }
57
65 bool
66 connect(Vertex source, Vertex target)
67 {
68 return connect(source, target, EdgeData{});
69 }
70
79 bool
80 disconnect(Vertex source, Vertex target)
81 {
82 auto it = graph_.find(source);
83 if (it != graph_.end())
84 {
85 return it->second.erase(target) > 0;
86 }
87 return false;
88 }
89
97 [[nodiscard]] std::optional<EdgeData>
98 edge(Vertex source, Vertex target) const
99 {
100 auto it = graph_.find(source);
101 if (it != graph_.end())
102 {
103 auto edgeIt = it->second.find(target);
104 if (edgeIt != it->second.end())
105 return edgeIt->second;
106 }
107 return std::nullopt;
108 }
109
116 [[nodiscard]] bool
117 connected(Vertex source, Vertex target) const
118 {
119 return edge(source, target) != std::nullopt;
120 }
121
127 [[nodiscard]] auto
129 {
130 return boost::adaptors::transform(
131 graph_, [](Graph::value_type const& v) { return v.first; });
132 }
133
139 [[nodiscard]] auto
140 outVertices(Vertex source) const
141 {
142 auto transform = [](Links::value_type const& link) { return link.first; };
143 auto it = graph_.find(source);
144 if (it != graph_.end())
145 return boost::adaptors::transform(it->second, transform);
146
147 return boost::adaptors::transform(empty_, transform);
148 }
149
152 struct Edge
153 {
154 Vertex source;
155 Vertex target;
156 EdgeData data;
157 };
158
165 [[nodiscard]] auto
166 outEdges(Vertex source) const
167 {
168 auto transform = [source](Links::value_type const& link) {
169 return Edge{source, link.first, link.second};
170 };
171
172 auto it = graph_.find(source);
173 if (it != graph_.end())
174 return boost::adaptors::transform(it->second, transform);
175
176 return boost::adaptors::transform(empty_, transform);
177 }
178
184 [[nodiscard]] std::size_t
185 outDegree(Vertex source) const
186 {
187 auto it = graph_.find(source);
188 if (it != graph_.end())
189 return it->second.size();
190 return 0;
191 }
192
201 template <class VertexName>
202 void
203 saveDot(std::ostream& out, VertexName&& vertexName) const
204 {
205 out << "digraph {\n";
206 for (auto const& [vertex, links] : graph_)
207 {
208 auto const fromName = vertexName(vertex);
209 for (auto const& eData : links)
210 {
211 auto const toName = vertexName(eData.first);
212 out << fromName << " -> " << toName << ";\n";
213 }
214 }
215 out << "}\n";
216 }
217
218 template <class VertexName>
219 void
220 saveDot(std::string const& fileName, VertexName&& vertexName) const
221 {
222 std::ofstream out(fileName);
223 saveDot(out, std::forward<VertexName>(vertexName));
224 }
225};
226
227} // namespace test::csf
228
229} // namespace xrpl
Directed graph.
Definition Digraph.h:35
std::size_t outDegree(Vertex source) const
Vertex out-degree.
Definition Digraph.h:185
void saveDot(std::string const &fileName, VertexName &&vertexName) const
Definition Digraph.h:220
auto outEdges(Vertex source) const
Range of out edges.
Definition Digraph.h:166
bool connected(Vertex source, Vertex target) const
Check if two vertices are connected.
Definition Digraph.h:117
bool connect(Vertex source, Vertex target, EdgeData e)
Connect two vertices.
Definition Digraph.h:53
auto outVertices(Vertex source) const
Range over target vertices.
Definition Digraph.h:140
boost::container::flat_map< Vertex, EdgeData > Links
Definition Digraph.h:36
bool disconnect(Vertex source, Vertex target)
Disconnect two vertices.
Definition Digraph.h:80
void saveDot(std::ostream &out, VertexName &&vertexName) const
Save GraphViz dot file.
Definition Digraph.h:203
std::optional< EdgeData > edge(Vertex source, Vertex target) const
Return edge data between two vertices.
Definition Digraph.h:98
auto outVertices() const
Range over vertices in the graph.
Definition Digraph.h:128
boost::container::flat_map< Vertex, Links > Graph
Definition Digraph.h:37
bool connect(Vertex source, Vertex target)
Connect two vertices using default constructed edge data.
Definition Digraph.h:66
T forward(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
Vertices and data associated with an Edge.
Definition Digraph.h:153