rippled
Loading...
Searching...
No Matches
Digraph.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012-2017 Ripple Labs Inc
5
6 Permission target use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef RIPPLE_TEST_CSF_DIGRAPH_H_INCLUDED
21#define RIPPLE_TEST_CSF_DIGRAPH_H_INCLUDED
22
23#include <boost/container/flat_map.hpp>
24#include <boost/range/adaptor/transformed.hpp>
25#include <boost/range/iterator_range.hpp>
26
27#include <fstream>
28#include <optional>
29#include <type_traits>
30#include <unordered_map>
31
32namespace ripple {
33namespace detail {
34// Dummy class when no edge data needed for graph
36{
37};
38
39} // namespace detail
40
41namespace test {
42namespace csf {
43
54template <class Vertex, class EdgeData = detail::NoEdgeData>
56{
57 using Links = boost::container::flat_map<Vertex, EdgeData>;
58 using Graph = boost::container::flat_map<Vertex, Links>;
60
61 // Allows returning empty iterables for unknown vertices
63
64public:
73 bool
74 connect(Vertex source, Vertex target, EdgeData e)
75 {
76 return graph_[source].emplace(target, e).second;
77 }
78
86 bool
87 connect(Vertex source, Vertex target)
88 {
89 return connect(source, target, EdgeData{});
90 }
91
100 bool
101 disconnect(Vertex source, Vertex target)
102 {
103 auto it = graph_.find(source);
104 if (it != graph_.end())
105 {
106 return it->second.erase(target) > 0;
107 }
108 return false;
109 }
110
119 edge(Vertex source, Vertex target) const
120 {
121 auto it = graph_.find(source);
122 if (it != graph_.end())
123 {
124 auto edgeIt = it->second.find(target);
125 if (edgeIt != it->second.end())
126 return edgeIt->second;
127 }
128 return std::nullopt;
129 }
130
137 bool
138 connected(Vertex source, Vertex target) const
139 {
140 return edge(source, target) != std::nullopt;
141 }
142
148 auto
150 {
151 return boost::adaptors::transform(
152 graph_,
153 [](typename Graph::value_type const& v) { return v.first; });
154 }
155
161 auto
162 outVertices(Vertex source) const
163 {
164 auto transform = [](typename Links::value_type const& link) {
165 return link.first;
166 };
167 auto it = graph_.find(source);
168 if (it != graph_.end())
169 return boost::adaptors::transform(it->second, transform);
170
171 return boost::adaptors::transform(empty, transform);
172 }
173
176 struct Edge
177 {
178 Vertex source;
179 Vertex target;
180 EdgeData data;
181 };
182
189 auto
190 outEdges(Vertex source) const
191 {
192 auto transform = [source](typename Links::value_type const& link) {
193 return Edge{source, link.first, link.second};
194 };
195
196 auto it = graph_.find(source);
197 if (it != graph_.end())
198 return boost::adaptors::transform(it->second, transform);
199
200 return boost::adaptors::transform(empty, transform);
201 }
202
209 outDegree(Vertex source) const
210 {
211 auto it = graph_.find(source);
212 if (it != graph_.end())
213 return it->second.size();
214 return 0;
215 }
216
225 template <class VertexName>
226 void
227 saveDot(std::ostream& out, VertexName&& vertexName) const
228 {
229 out << "digraph {\n";
230 for (auto const& [vertex, links] : graph_)
231 {
232 auto const fromName = vertexName(vertex);
233 for (auto const& eData : links)
234 {
235 auto const toName = vertexName(eData.first);
236 out << fromName << " -> " << toName << ";\n";
237 }
238 }
239 out << "}\n";
240 }
241
242 template <class VertexName>
243 void
244 saveDot(std::string const& fileName, VertexName&& vertexName) const
245 {
246 std::ofstream out(fileName);
248 }
249};
250
251} // namespace csf
252} // namespace test
253} // namespace ripple
254#endif
Directed graph.
Definition Digraph.h:56
bool connect(Vertex source, Vertex target)
Connect two vertices using default constructed edge data.
Definition Digraph.h:87
boost::container::flat_map< Vertex, EdgeData > Links
Definition Digraph.h:57
bool connected(Vertex source, Vertex target) const
Check if two vertices are connected.
Definition Digraph.h:138
boost::container::flat_map< Vertex, Links > Graph
Definition Digraph.h:58
auto outVertices() const
Range over vertices in the graph.
Definition Digraph.h:149
void saveDot(std::ostream &out, VertexName &&vertexName) const
Save GraphViz dot file.
Definition Digraph.h:227
auto outVertices(Vertex source) const
Range over target vertices.
Definition Digraph.h:162
auto outEdges(Vertex source) const
Range of out edges.
Definition Digraph.h:190
std::size_t outDegree(Vertex source) const
Vertex out-degree.
Definition Digraph.h:209
std::optional< EdgeData > edge(Vertex source, Vertex target) const
Return edge data between two vertices.
Definition Digraph.h:119
void saveDot(std::string const &fileName, VertexName &&vertexName) const
Definition Digraph.h:244
bool disconnect(Vertex source, Vertex target)
Disconnect two vertices.
Definition Digraph.h:101
bool connect(Vertex source, Vertex target, EdgeData e)
Connect two vertices.
Definition Digraph.h:74
T is_same_v
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
Vertices and data associated with an Edge.
Definition Digraph.h:177