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 <cstddef>
8#include <fstream>
9#include <optional>
10#include <ostream>
11#include <string>
12
13namespace xrpl {
14namespace detail {
15// Dummy class when no edge data needed for graph
17{
18};
19
20} // namespace detail
21
22namespace test::csf {
23
34template <class Vertex, class EdgeData = detail::NoEdgeData>
36{
37 using Links = boost::container::flat_map<Vertex, EdgeData>;
38 using Graph = boost::container::flat_map<Vertex, Links>;
40
41 // Allows returning empty iterables for unknown vertices
43
44public:
53 bool
54 connect(Vertex source, Vertex target, EdgeData e)
55 {
56 return graph_[source].emplace(target, e).second;
57 }
58
66 bool
67 connect(Vertex source, Vertex target)
68 {
69 return connect(source, target, EdgeData{});
70 }
71
81 bool
82 disconnect(Vertex source, Vertex target)
83 {
84 auto it = graph_.find(source);
85 if (it != graph_.end())
86 {
87 return it->second.erase(target) > 0;
88 }
89 return false;
90 }
91
99 [[nodiscard]] std::optional<EdgeData>
100 edge(Vertex source, Vertex target) const
101 {
102 auto it = graph_.find(source);
103 if (it != graph_.end())
104 {
105 auto edgeIt = it->second.find(target);
106 if (edgeIt != it->second.end())
107 return edgeIt->second;
108 }
109 return std::nullopt;
110 }
111
119 [[nodiscard]] bool
120 connected(Vertex source, Vertex target) const
121 {
122 return edge(source, target) != std::nullopt;
123 }
124
131 [[nodiscard]] auto
133 {
134 return boost::adaptors::transform(
135 graph_, [](Graph::value_type const& v) { return v.first; });
136 }
137
144 [[nodiscard]] auto
145 outVertices(Vertex source) const
146 {
147 auto transform = [](Links::value_type const& link) { return link.first; };
148 auto it = graph_.find(source);
149 if (it != graph_.end())
150 return boost::adaptors::transform(it->second, transform);
151
152 return boost::adaptors::transform(empty_, transform);
153 }
154
158 struct Edge
159 {
160 Vertex source;
161 Vertex target;
162 EdgeData data;
163 };
164
172 [[nodiscard]] auto
173 outEdges(Vertex source) const
174 {
175 auto transform = [source](Links::value_type const& link) {
176 return Edge{source, link.first, link.second};
177 };
178
179 auto it = graph_.find(source);
180 if (it != graph_.end())
181 return boost::adaptors::transform(it->second, transform);
182
183 return boost::adaptors::transform(empty_, transform);
184 }
185
192 [[nodiscard]] std::size_t
193 outDegree(Vertex source) const
194 {
195 auto it = graph_.find(source);
196 if (it != graph_.end())
197 return it->second.size();
198 return 0;
199 }
200
210 template <class VertexName>
211 void
212 saveDot(std::ostream& out, VertexName&& vertexName) const
213 {
214 out << "digraph {\n";
215 for (auto const& [vertex, links] : graph_)
216 {
217 auto const fromName = vertexName(vertex);
218 for (auto const& eData : links)
219 {
220 auto const toName = vertexName(eData.first);
221 out << fromName << " -> " << toName << ";\n";
222 }
223 }
224 out << "}\n";
225 }
226
227 template <class VertexName>
228 void
229 saveDot(std::string const& fileName, VertexName&& vertexName) const
230 {
231 std::ofstream out(fileName);
232 saveDot(out, std::forward<VertexName>(vertexName));
233 }
234};
235
236} // namespace test::csf
237
238} // namespace xrpl
Directed graph.
Definition Digraph.h:36
std::size_t outDegree(Vertex source) const
Vertex out-degree.
Definition Digraph.h:193
void saveDot(std::string const &fileName, VertexName &&vertexName) const
Definition Digraph.h:229
auto outEdges(Vertex source) const
Range of out edges.
Definition Digraph.h:173
bool connected(Vertex source, Vertex target) const
Check if two vertices are connected.
Definition Digraph.h:120
bool connect(Vertex source, Vertex target, EdgeData e)
Connect two vertices.
Definition Digraph.h:54
auto outVertices(Vertex source) const
Range over target vertices.
Definition Digraph.h:145
boost::container::flat_map< Vertex, EdgeData > Links
Definition Digraph.h:37
bool disconnect(Vertex source, Vertex target)
Disconnect two vertices.
Definition Digraph.h:82
void saveDot(std::ostream &out, VertexName &&vertexName) const
Save GraphViz dot file.
Definition Digraph.h:212
std::optional< EdgeData > edge(Vertex source, Vertex target) const
Return edge data between two vertices.
Definition Digraph.h:100
auto outVertices() const
Range over vertices in the graph.
Definition Digraph.h:132
boost::container::flat_map< Vertex, Links > Graph
Definition Digraph.h:38
bool connect(Vertex source, Vertex target)
Connect two vertices using default constructed edge data.
Definition Digraph.h:67
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:159