GraphAlgorithms.hh
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017 Open Source Robotics Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16*/
17#ifndef GZ_MATH_GRAPH_GRAPHALGORITHMS_HH_
18#define GZ_MATH_GRAPH_GRAPHALGORITHMS_HH_
19
20#include <functional>
21#include <list>
22#include <map>
23#include <queue>
24#include <stack>
25#include <utility>
26#include <vector>
27
28#include <gz/math/config.hh>
29#include "gz/math/detail/Error.hh"
31#include "gz/math/Helpers.hh"
32
33namespace gz::math
34{
35// Inline bracket to help doxygen filtering.
36inline namespace GZ_MATH_VERSION_NAMESPACE {
37namespace graph
38{
43
50 template<typename V, typename E, typename EdgeType>
52 const VertexId &_from)
53 {
54 // Create an auxiliary graph, where the data is just a boolean value that
55 // stores whether the vertex has been visited or not.
57
58 // Copy the vertices (just the Id).
59 for (auto const &v : _graph.Vertices())
60 visitorGraph.AddVertex("", false, v.first);
61
62 // Copy the edges (without data).
63 for (auto const &e : _graph.Edges())
64 visitorGraph.AddEdge(e.second.get().Vertices(), E());
65
68
69 while (!pending.empty())
70 {
71 auto vId = pending.front();
72 pending.pop_front();
73
74 // If the vertex has been visited, skip.
75 auto &vertex = visitorGraph.VertexFromId(vId);
76 if (vertex.Data())
77 continue;
78
79 visited.push_back(vId);
80 vertex.Data() = true;
81
82 // Add more vertices to visit if they haven't been visited yet.
83 auto adjacents = visitorGraph.AdjacentsFrom(vId);
84 for (auto const &adj : adjacents)
85 {
86 vId = adj.first;
87 auto &v = adj.second.get();
88 if (!v.Data())
89 pending.push_back(vId);
90 }
91 }
92
93 return visited;
94 }
95
102 template<typename V, typename E, typename EdgeType>
104 const VertexId &_from)
105 {
106 // Create an auxiliary graph, where the data is just a boolean value that
107 // stores whether the vertex has been visited or not.
109
110 // Copy the vertices (just the Id).
111 for (auto const &v : _graph.Vertices())
112 visitorGraph.AddVertex("", false, v.first);
113
114 // Copy the edges (without data).
115 for (auto const &e : _graph.Edges())
116 visitorGraph.AddEdge(e.second.get().Vertices(), E());
117
120
121 while (!pending.empty())
122 {
123 auto vId = pending.top();
124 pending.pop();
125
126 // If the vertex has been visited, skip.
127 auto &vertex = visitorGraph.VertexFromId(vId);
128 if (vertex.Data())
129 continue;
130
131 visited.push_back(vId);
132 vertex.Data() = true;
133
134 // Add more vertices to visit if they haven't been visited yet.
135 auto adjacents = visitorGraph.AdjacentsFrom(vId);
136 for (auto const &adj : adjacents)
137 {
138 vId = adj.first;
139 auto &v = adj.second.get();
140 if (!v.Data())
141 pending.push(vId);
142 }
143 }
144
145 return visited;
146 }
147
211 template<typename V, typename E, typename EdgeType>
213 const VertexId &_from,
214 const VertexId &_to = kNullId)
215 {
216 auto allVertices = _graph.Vertices();
217
218 // Sanity check: The source vertex should exist.
219 if (allVertices.find(_from) == allVertices.end())
220 {
222 errStream << "Vertex [" << _from << "] Not found";
223 detail::LogErrorMessage(errStream.str());
224 return {};
225 }
226
227 // Sanity check: The destination vertex should exist (if used).
228 if (_to != kNullId &&
229 allVertices.find(_to) == allVertices.end())
230 {
232 errStream << "Vertex [" << _from << "] Not found";
233 detail::LogErrorMessage(errStream.str());
234 return {};
235 }
236
237 // Store vertices that are being preprocessed.
240
241 // Create a map for distances and next neighbor and initialize all
242 // distances as infinite.
244 for (auto const &v : allVertices)
245 {
246 auto id = v.first;
247 dist[id] = std::make_pair(MAX_D, kNullId);
248 }
249
250 // Insert _from in the priority queue and initialize its distance as 0.
251 pq.push(std::make_pair(0.0, _from));
253
254 while (!pq.empty())
255 {
256 // This is the minimum distance vertex.
257 VertexId u = pq.top().second;
258
259 // Shortcut: Destination vertex found, exiting.
260 if (_to != kNullId && _to == u)
261 break;
262
263 pq.pop();
264
265 for (auto const &edgePair : _graph.IncidentsFrom(u))
266 {
267 const auto &edge = edgePair.second.get();
268 const auto &v = edge.From(u);
269 double weight = edge.Weight();
270
271 // If there is shorted path to v through u.
272 if (dist[v].first > dist[u].first + weight)
273 {
274 // Updating distance of v.
275 dist[v] = std::make_pair(dist[u].first + weight, u);
276 pq.push(std::make_pair(dist[v].first, v));
277 }
278 }
279 }
280
281 return dist;
282 }
283
292 template<typename V, typename E>
295 {
297 unsigned int componentCount = 0;
298
299 for (auto const &v : _graph.Vertices())
300 {
301 if (visited.find(v.first) == visited.end())
302 {
303 auto component = BreadthFirstSort(_graph, v.first);
304 for (auto const &vId : component)
307 }
308 }
309
311
312 // Create the vertices.
313 for (auto const &vPair : _graph.Vertices())
314 {
315 const auto &v = vPair.second.get();
316 const auto &componentId = visited[v.Id()];
317 res[componentId].AddVertex(v.Name(), v.Data(), v.Id());
318 }
319
320 // Create the edges.
321 for (auto const &ePair : _graph.Edges())
322 {
323 const auto &e = ePair.second.get();
324 const auto &vertices = e.Vertices();
325 const auto &componentId = visited[vertices.first];
326 res[componentId].AddEdge(vertices, e.Data(), e.Weight());
327 }
328
329 return res;
330 }
331
337 template<typename V, typename E>
339 {
340 std::vector<Vertex<V>> vertices;
342
343 // Add all vertices.
344 for (auto const &vPair : _graph.Vertices())
345 {
346 // cppcheck-suppress useStlAlgorithm
347 vertices.push_back(vPair.second.get());
348 }
349
350 // Add all edges.
351 for (auto const &ePair : _graph.Edges())
352 {
353 auto const &e = ePair.second.get();
354 edges.push_back({e.Vertices(), e.Data(), e.Weight()});
355 }
356
357 return UndirectedGraph<V, E>(vertices, edges);
358 }
359} // namespace graph
360} // namespace GZ_MATH_VERSION_NAMESPACE
361} // namespace gz::math
362#endif // GZ_MATH_GRAPH_GRAPHALGORITHMS_HH_