Gazebo Math
API Reference
8.1.1
insert_drive_file
Tutorials
library_books
Classes
toc
Namespaces
insert_drive_file
Files
launch
Gazebo Website
Index
List
Hierarchy
Members: All
Members: Functions
Members: Variables
Members: Typedefs
Members: Enumerations
Members: Enumerator
List
Members
Functions
Typedefs
Variables
Enumerations
Enumerator
src
gz-math
include
gz
math
graph
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"
30
#include "
gz/math/graph/Graph.hh
"
31
#include "
gz/math/Helpers.hh
"
32
33
namespace
gz::math
34
{
35
// Inline bracket to help doxygen filtering.
36
inline
namespace
GZ_MATH_VERSION_NAMESPACE {
37
namespace
graph
38
{
42
using
CostInfo
=
std::pair<double, VertexId>
;
43
50
template
<
typename
V,
typename
E,
typename
EdgeType>
51
std::vector<VertexId>
BreadthFirstSort
(
const
Graph<V, E, EdgeType>
&
_graph
,
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.
56
Graph<bool, E, EdgeType>
visitorGraph
;
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
66
std::vector<VertexId>
visited
;
67
std::list<VertexId>
pending
= {
_from
};
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>
103
std::vector<VertexId>
DepthFirstSort
(
const
Graph<V, E, EdgeType>
&
_graph
,
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.
108
Graph<bool, E, EdgeType>
visitorGraph
;
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
118
std::vector<VertexId>
visited
;
119
std::stack<VertexId>
pending
({
_from
});
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>
212
std::map<VertexId, CostInfo>
Dijkstra
(
const
Graph<V, E, EdgeType>
&
_graph
,
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
{
221
std::ostringstream
errStream
;
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
{
231
std::ostringstream
errStream
;
232
errStream
<<
"Vertex ["
<<
_from
<<
"] Not found"
;
233
detail::LogErrorMessage(
errStream
.str());
234
return
{};
235
}
236
237
// Store vertices that are being preprocessed.
238
std::priority_queue
<
CostInfo
,
239
std::vector<CostInfo>
,
std::greater<CostInfo>
>
pq
;
240
241
// Create a map for distances and next neighbor and initialize all
242
// distances as infinite.
243
std::map<VertexId, CostInfo>
dist
;
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
));
252
dist
[
_from
] =
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>
293
std::vector<UndirectedGraph<V, E>
>
ConnectedComponents
(
294
const
UndirectedGraph<V, E>
&
_graph
)
295
{
296
std::map<VertexId, unsigned int>
visited
;
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
)
305
visited
[
vId
] =
componentCount
;
306
++
componentCount
;
307
}
308
}
309
310
std::vector<UndirectedGraph<V, E>
>
res
(
componentCount
);
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>
338
UndirectedGraph<V, E>
ToUndirectedGraph
(
const
DirectedGraph<V, E>
&
_graph
)
339
{
340
std::vector<Vertex<V>
> vertices;
341
std::vector<EdgeInitializer<E>
> edges;
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_