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
Graph.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_GRAPH_HH_
18
#define GZ_MATH_GRAPH_GRAPH_HH_
19
20
#include <cassert>
21
#include <map>
22
#include <ostream>
23
#include <set>
24
#include <sstream>
25
#include <string>
26
#include <utility>
27
#include <vector>
28
29
#include <gz/math/config.hh>
30
#include "gz/math/detail/Error.hh"
31
#include "
gz/math/graph/Edge.hh
"
32
#include "
gz/math/graph/Vertex.hh
"
33
34
namespace
gz::math
35
{
36
// Inline bracket to help doxygen filtering.
37
inline
namespace
GZ_MATH_VERSION_NAMESPACE {
38
namespace
graph
39
{
48
//
101
template
<
typename
V,
typename
E,
typename
EdgeType>
102
class
Graph
103
{
105
public
:
Graph
() =
default
;
106
110
public
:
Graph
(
const
std::vector
<
Vertex<V>
> &
_vertices
,
111
const
std::vector
<
EdgeInitializer<E>
> &
_edges
)
112
{
113
// Add all vertices.
114
for
(
auto
const
&
v
:
_vertices
)
115
{
116
if
(!this->AddVertex(
v
.Name(),
v
.Data(),
v
.Id()).Valid())
117
{
118
std::ostringstream
errStream
;
119
errStream
<<
"Invalid vertex with Id ["
<<
v
.Id() <<
"]. Ignoring."
;
120
detail::LogErrorMessage(
errStream
.str());
121
}
122
}
123
124
// Add all edges.
125
for
(
auto
const
&
e
:
_edges
)
126
{
127
if
(!this->AddEdge(
e
.vertices,
e
.data,
e
.weight).Valid())
128
detail::LogErrorMessage(
"Ignoring edge"
);
129
}
130
}
131
138
public
:
Vertex<V>
&
AddVertex
(
const
std::string
&
_name
,
139
const
V
&
_data
,
140
const
VertexId
&
_id
= kNullId)
141
{
142
auto
id
=
_id
;
143
144
// The user didn't provide an Id, we generate it.
145
if
(
id
==
kNullId
)
146
{
147
id
= this->NextVertexId();
148
149
// No space for new Ids.
150
if
(
id
==
kNullId
)
151
{
152
detail::LogErrorMessage(
153
"[Graph::AddVertex()] The limit of vertices has been reached. "
154
"Ignoring vertex."
);
155
return
NullVertex<V>
();
156
}
157
}
158
159
// Create the vertex.
160
auto
ret
= this->vertices.insert(
161
std::make_pair
(
id
,
Vertex<V>
(
_name
,
_data
,
id
)));
162
163
// The Id already exists.
164
if
(!
ret
.second)
165
{
166
std::ostringstream
errStream
;
167
errStream
<<
"[Graph::AddVertex()] Repeated vertex ["
<<
id
<<
"]"
;
168
detail::LogErrorMessage(
errStream
.str());
169
return
NullVertex<V>
();
170
}
171
172
// Link the vertex with an empty list of edges.
173
this->adjList[id] =
EdgeId_S
();
174
175
// Update the map of names.
176
this->names.insert(
std::make_pair
(
_name
,
id
));
177
178
return
ret
.first->second;
179
}
180
184
public
:
const
VertexRef_M<V>
Vertices
()
const
185
{
186
VertexRef_M<V>
res
;
187
for
(
auto
const
&
v
: this->vertices)
188
res
.emplace(
std::make_pair
(
v
.first,
std::cref
(
v
.second)));
189
190
return
res
;
191
}
192
196
public
:
const
VertexRef_M<V>
Vertices
(
const
std::string
&
_name
)
const
197
{
198
VertexRef_M<V>
res
;
199
for
(
auto
const
&
vertex
: this->vertices)
200
{
201
if
(
vertex
.second.Name() ==
_name
)
202
res
.emplace(
std::make_pair
(
vertex
.first,
std::cref
(
vertex
.second)));
203
}
204
205
return
res
;
206
}
207
214
public
:
EdgeType
&
AddEdge
(
const
VertexId_P
&
_vertices
,
215
const
E
&
_data
,
216
const
double
_weight
= 1.0)
217
{
218
auto
id
= this->NextEdgeId();
219
220
// No space for new Ids.
221
if
(
id
==
kNullId
)
222
{
223
detail::LogErrorMessage(
224
"[Graph::AddEdge()] The limit of edges has been reached. "
225
"Ignoring edge."
);
226
return
NullEdge<E, EdgeType>
();
227
}
228
229
EdgeType
newEdge
(
_vertices
,
_data
,
_weight
,
id
);
230
return
this->LinkEdge(
std::move
(
newEdge
));
231
}
232
239
public
:
EdgeType
&
LinkEdge
(
const
EdgeType
&
_edge
)
240
{
241
auto
edgeVertices
=
_edge
.Vertices();
242
243
// Sanity check: Both vertices should exist.
244
for
(
auto
const
&
v
: {
edgeVertices
.first,
edgeVertices
.second})
245
{
246
if
(this->vertices.find(
v
) == this->vertices.end())
247
return
NullEdge<E, EdgeType>
();
248
}
249
250
// Link the new edge.
251
for
(
auto
const
&
v
: {
edgeVertices
.first,
edgeVertices
.second})
252
{
253
if
(
v
!=
kNullId
)
254
{
255
auto
vertexIt
= this->adjList.find(
v
);
256
assert
(
vertexIt
!= this->adjList.end());
257
vertexIt
->second.insert(
_edge
.Id());
258
}
259
}
260
261
auto
ret
= this->edges.insert(
std::make_pair
(
_edge
.Id(),
_edge
));
262
263
// Return the new edge.
264
return
ret
.first->second;
265
}
266
270
public
:
const
EdgeRef_M<EdgeType>
Edges
()
const
271
{
272
EdgeRef_M<EdgeType>
res
;
273
for
(
auto
const
&
edge
: this->edges)
274
{
275
res
.emplace(
std::make_pair
(
edge
.first,
std::cref
(
edge
.second)));
276
}
277
278
return
res
;
279
}
280
296
public
:
VertexRef_M<V>
AdjacentsFrom
(
const
VertexId
&
_vertex
)
const
297
{
298
VertexRef_M<V>
res
;
299
300
// Make sure the vertex exists
301
auto
vertexIt
= this->adjList.find(
_vertex
);
302
if
(
vertexIt
== this->adjList.end())
303
return
res
;
304
305
for
(
auto
const
&
edgeId
:
vertexIt
->second)
306
{
307
const
auto
&
edge
= this->EdgeFromId(
edgeId
);
308
auto
neighborVertexId
=
edge
.From(
_vertex
);
309
if
(
neighborVertexId
!=
kNullId
)
310
{
311
const
auto
&
neighborVertex
= this->VertexFromId(
neighborVertexId
);
312
res
.emplace(
313
std::make_pair
(
neighborVertexId
,
std::cref
(
neighborVertex
)));
314
}
315
}
316
317
return
res
;
318
}
319
335
public
:
VertexRef_M<V>
AdjacentsFrom
(
const
Vertex<V>
&
_vertex
)
const
336
{
337
return
this->AdjacentsFrom(
_vertex
.Id());
338
}
339
355
public
:
VertexRef_M<V>
AdjacentsTo
(
const
VertexId
&
_vertex
)
const
356
{
357
auto
incidentEdges
= this->IncidentsTo(
_vertex
);
358
359
VertexRef_M<V>
res
;
360
for
(
auto
const
&
incidentEdgeRef
:
incidentEdges
)
361
{
362
const
auto
&
incidentEdgeId
=
incidentEdgeRef
.first;
363
const
auto
&
incidentEdge
= this->EdgeFromId(
incidentEdgeId
);
364
const
auto
&
neighborVertexId
=
incidentEdge
.To(
_vertex
);
365
const
auto
&
neighborVertex
= this->VertexFromId(
neighborVertexId
);
366
res
.emplace(
367
std::make_pair
(
neighborVertexId
,
std::cref
(
neighborVertex
)));
368
}
369
370
return
res
;
371
}
372
388
public
:
VertexRef_M<V>
AdjacentsTo
(
const
Vertex<V>
&
_vertex
)
const
389
{
390
return
this->AdjacentsTo(
_vertex
.Id());
391
}
392
396
public
:
size_t
InDegree
(
const
VertexId
&
_vertex
)
const
397
{
398
return
this->IncidentsTo(
_vertex
).size();
399
}
400
404
public
:
size_t
InDegree
(
const
Vertex<V>
&
_vertex
)
const
405
{
406
return
this->IncidentsTo(this->VertexFromId(
_vertex
.Id())).size();
407
}
408
412
public
:
size_t
OutDegree
(
const
VertexId
&
_vertex
)
const
413
{
414
return
this->IncidentsFrom(
_vertex
).size();
415
}
416
420
public
:
size_t
OutDegree
(
const
Vertex<V>
&
_vertex
)
const
421
{
422
return
this->IncidentsFrom(this->VertexFromId(
_vertex
.Id())).size();
423
}
424
430
public
:
const
EdgeRef_M<EdgeType>
IncidentsFrom
(
const
VertexId
&
_vertex
)
431
const
432
{
433
EdgeRef_M<EdgeType>
res
;
434
435
const
auto
&
adjIt
= this->adjList.find(
_vertex
);
436
if
(
adjIt
== this->adjList.end())
437
return
res
;
438
439
const
auto
&
edgeIds
=
adjIt
->second;
440
for
(
auto
const
&
edgeId
:
edgeIds
)
441
{
442
const
auto
&
edge
= this->EdgeFromId(
edgeId
);
443
if
(
edge
.From(
_vertex
) !=
kNullId
)
444
res
.emplace(
std::make_pair
(
edge
.Id(),
std::cref
(
edge
)));
445
}
446
447
return
res
;
448
}
449
455
public
:
const
EdgeRef_M<EdgeType>
IncidentsFrom
(
456
const
Vertex<V>
&
_vertex
)
const
457
{
458
return
this->IncidentsFrom(
_vertex
.Id());
459
}
460
466
public
:
const
EdgeRef_M<EdgeType>
IncidentsTo
(
467
const
VertexId
&
_vertex
)
const
468
{
469
EdgeRef_M<EdgeType>
res
;
470
471
const
auto
&
adjIt
= this->adjList.find(
_vertex
);
472
if
(
adjIt
== this->adjList.end())
473
return
res
;
474
475
const
auto
&
edgeIds
=
adjIt
->second;
476
for
(
auto
const
&
edgeId
:
edgeIds
)
477
{
478
const
auto
&
edge
= this->EdgeFromId(
edgeId
);
479
if
(
edge
.To(
_vertex
) !=
kNullId
)
480
res
.emplace(
std::make_pair
(
edge
.Id(),
std::cref
(
edge
)));
481
}
482
483
return
res
;
484
}
485
491
public
:
const
EdgeRef_M<EdgeType>
IncidentsTo
(
const
Vertex<V>
&
_vertex
)
492
const
493
{
494
return
this->IncidentsTo(
_vertex
.Id());
495
}
496
500
public
:
bool
Empty
()
const
501
{
502
return
this->vertices.empty();
503
}
504
508
public
:
bool
RemoveVertex
(
const
VertexId
&
_vertex
)
509
{
510
auto
vIt
= this->vertices.find(
_vertex
);
511
if
(
vIt
== this->vertices.end())
512
return
false
;
513
514
std::string
name =
vIt
->second.Name();
515
516
// Remove incident edges.
517
auto
incidents
= this->IncidentsTo(
_vertex
);
518
for
(
auto
edgePair
:
incidents
)
519
this->RemoveEdge(
edgePair
.first);
520
521
// Remove all outgoing edges.
522
incidents
= this->IncidentsFrom(
_vertex
);
523
for
(
auto
edgePair
:
incidents
)
524
this->RemoveEdge(
edgePair
.first);
525
526
// Remove the vertex (key) from the adjacency list.
527
this->adjList.erase(
_vertex
);
528
529
// Remove the vertex.
530
this->vertices.erase(
_vertex
);
531
532
// Get an iterator to all vertices sharing name.
533
auto
iterPair
= this->names.equal_range(name);
534
for
(
auto
it
=
iterPair
.first;
it
!=
iterPair
.second; ++
it
)
535
{
536
if
(
it
->second ==
_vertex
)
537
{
538
this->names.erase(
it
);
539
break
;
540
}
541
}
542
543
return
true
;
544
}
545
549
public
:
bool
RemoveVertex
(
Vertex<V>
&
_vertex
)
550
{
551
return
this->RemoveVertex(
_vertex
.Id());
552
}
553
557
public
:
size_t
RemoveVertices
(
const
std::string
&
_name
)
558
{
559
size_t
numVertices
= this->names.count(
_name
);
560
size_t
result
= 0;
561
for
(
size_t
i
= 0;
i
<
numVertices
; ++
i
)
562
{
563
auto
iter = this->names.find(
_name
);
564
if
(this->RemoveVertex(iter->second))
565
++
result
;
566
}
567
568
return
result
;
569
}
570
576
public
:
bool
RemoveEdge
(
const
EdgeId
&
_edge
)
577
{
578
auto
edgeIt
= this->edges.find(
_edge
);
579
if
(
edgeIt
== this->edges.end())
580
return
false
;
581
582
auto
edgeVertices
=
edgeIt
->second.Vertices();
583
584
// Unlink the edge.
585
for
(
auto
const
&
v
: {
edgeVertices
.first,
edgeVertices
.second})
586
{
587
if
(
edgeIt
->second.From(
v
) !=
kNullId
)
588
{
589
auto
vertex
= this->adjList.find(
v
);
590
assert
(
vertex
!= this->adjList.end());
591
vertex
->second.erase(
_edge
);
592
}
593
}
594
595
this->edges.erase(
_edge
);
596
597
return
true
;
598
}
599
605
public
:
bool
RemoveEdge
(
EdgeType
&
_edge
)
606
{
607
return
this->RemoveEdge(
_edge
.Id());
608
}
609
614
public
:
const
Vertex<V>
&
VertexFromId
(
const
VertexId
&
_id
)
const
615
{
616
auto
iter = this->vertices.find(
_id
);
617
if
(iter == this->vertices.end())
618
return
NullVertex<V>
();
619
620
return
iter->second;
621
}
622
627
public
:
Vertex<V>
&
VertexFromId
(
const
VertexId
&
_id
)
628
{
629
auto
iter = this->vertices.find(
_id
);
630
if
(iter == this->vertices.end())
631
return
NullVertex<V>
();
632
633
return
iter->second;
634
}
635
644
public
:
const
EdgeType
&
EdgeFromVertices
(
645
const
VertexId
_sourceId
,
const
VertexId
_destId
)
const
646
{
647
// Get the adjacency iterator for the source vertex.
648
const
typename
std::map<VertexId, EdgeId_S>::const_iterator
&
adjIt
=
649
this->adjList.find(
_sourceId
);
650
651
// Quit early if there is no adjacency entry
652
if
(
adjIt
== this->adjList.end())
653
return
NullEdge<E, EdgeType>
();
654
655
// Loop over the edges in the source vertex's adjacency list
656
for
(
std::set<EdgeId>::const_iterator
edgIt
=
adjIt
->second.begin();
657
edgIt
!=
adjIt
->second.end(); ++
edgIt
)
658
{
659
// Get an iterator to the actual edge
660
const
typename
std::map<EdgeId, EdgeType>::const_iterator
edgeIter
=
661
this->edges.find(*
edgIt
);
662
663
// Check if the edge has the correct source and destination.
664
if
(
edgeIter
!= this->edges.end() &&
665
edgeIter
->second.From(
_sourceId
) ==
_destId
)
666
{
667
assert
(
edgeIter
->second.To(
_destId
) ==
_sourceId
);
668
return
edgeIter
->second;
669
}
670
}
671
672
return
NullEdge<E, EdgeType>
();
673
}
674
679
public
:
const
EdgeType
&
EdgeFromId
(
const
EdgeId
&
_id
)
const
680
{
681
auto
iter = this->edges.find(
_id
);
682
if
(iter == this->edges.end())
683
return
NullEdge<E, EdgeType>
();
684
685
return
iter->second;
686
}
687
692
public
:
EdgeType
&
EdgeFromId
(
const
EdgeId
&
_id
)
693
{
694
auto
iter = this->edges.find(
_id
);
695
if
(iter == this->edges.end())
696
return
NullEdge<E, EdgeType>
();
697
698
return
iter->second;
699
}
700
706
public
:
template
<
typename
VV,
typename
EE,
typename
EEdgeType>
707
friend
std::ostream
&
operator<<
(
std::ostream
&
_out
,
708
const
Graph<VV, EE, EEdgeType>
&
_g
);
709
712
private
:
VertexId
&NextVertexId()
713
{
714
while
(this->vertices.find(
this
->nextVertexId) !=
this
->vertices.end()
715
&&
this
->nextVertexId < MAX_UI64)
716
{
717
++this->nextVertexId;
718
}
719
720
return
this->nextVertexId;
721
}
722
725
private
: VertexId &NextEdgeId()
726
{
727
while
(this->edges.find(
this
->nextEdgeId) !=
this
->edges.end() &&
728
this
->nextEdgeId < MAX_UI64)
729
{
730
++this->nextEdgeId;
731
}
732
733
return
this->nextEdgeId;
734
}
735
737
protected
:
VertexId
nextVertexId = 0
u
;
738
740
protected
:
VertexId
nextEdgeId = 0
u
;
741
743
private
:
std::map<VertexId, Vertex<V>
> vertices;
744
746
private
:
std::map<EdgeId, EdgeType>
edges;
747
753
private
:
std::map<VertexId, EdgeId_S>
adjList;
754
756
private
:
std::multimap<std::string, VertexId>
names;
757
};
758
761
template
<
typename
VV,
typename
EE>
762
std::ostream
&
operator<<
(
std::ostream
&
_out
,
763
const
Graph
<
VV
,
EE
,
UndirectedEdge<EE>
> &
_g
)
764
{
765
_out
<<
"graph {"
<<
std::endl
;
766
767
// All vertices with the name and Id as a "label" attribute.
768
for
(
auto
const
&
vertexMap
:
_g
.Vertices())
769
{
770
auto
vertex
=
vertexMap
.second.get();
771
_out
<<
vertex
;
772
}
773
774
// All edges.
775
for
(
auto
const
&
edgeMap
:
_g
.Edges())
776
{
777
auto
edge
=
edgeMap
.second.get();
778
_out
<<
edge
;
779
}
780
781
_out
<<
"}"
<<
std::endl
;
782
783
return
_out
;
784
}
785
788
template
<
typename
VV,
typename
EE>
789
std::ostream
&
operator<<
(
std::ostream
&
_out
,
790
const
Graph
<
VV
,
EE
,
DirectedEdge<EE>
> &
_g
)
791
{
792
_out
<<
"digraph {"
<<
std::endl
;
793
794
// All vertices with the name and Id as a "label" attribute.
795
for
(
auto
const
&
vertexMap
:
_g
.Vertices())
796
{
797
auto
vertex
=
vertexMap
.second.get();
798
_out
<<
vertex
;
799
}
800
801
// All edges.
802
for
(
auto
const
&
edgeMap
:
_g
.Edges())
803
{
804
auto
edge
=
edgeMap
.second.get();
805
_out
<<
edge
;
806
}
807
808
_out
<<
"}"
<<
std::endl
;
809
810
return
_out
;
811
}
812
815
template
<
typename
V,
typename
E>
816
using
UndirectedGraph
=
Graph<V, E, UndirectedEdge<E>
>;
817
820
template
<
typename
V,
typename
E>
821
using
DirectedGraph
=
Graph<V, E, DirectedEdge<E>
>;
822
}
// namespace graph
823
}
// namespace GZ_MATH_VERSION_NAMESPACE
824
}
// namespace gz::math::graph
825
#endif
// GZ_MATH_GRAPH_GRAPH_HH_