Gazebo Math
API Reference
9.2.0
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 <iterator>
22
#include <map>
23
#include <ostream>
24
#include <set>
25
#include <sstream>
26
#include <string>
27
#include <utility>
28
#include <vector>
29
30
#include <gz/math/config.hh>
31
#include "gz/math/detail/Error.hh"
32
#include "
gz/math/graph/Edge.hh
"
33
#include "
gz/math/graph/Vertex.hh
"
34
35
namespace
gz::math
36
{
37
// Inline bracket to help doxygen filtering.
38
inline
namespace
GZ_MATH_VERSION_NAMESPACE {
39
namespace
graph
40
{
55
//
108
template
<
typename
V,
typename
E,
typename
EdgeType>
109
class
Graph
110
{
112
public
:
Graph
() =
default
;
113
117
public
:
Graph
(
const
std::vector
<
Vertex<V>
> &
_vertices
,
118
const
std::vector
<
EdgeInitializer<E>
> &
_edges
)
119
{
120
// Add all vertices.
121
for
(
auto
const
&
v
:
_vertices
)
122
{
123
if
(!this->AddVertex(
v
.Name(),
v
.
Data
(),
v
.Id()).Valid())
124
{
125
std::ostringstream
errStream
;
126
errStream
<<
"Invalid vertex with Id ["
<<
v
.Id() <<
"]. Ignoring."
;
127
detail::LogErrorMessage(
errStream
.str());
128
}
129
}
130
131
// Add all edges.
132
for
(
auto
const
&
e
:
_edges
)
133
{
134
if
(!this->AddEdge(
e
.vertices,
e
.data,
e
.weight).Valid())
135
detail::LogErrorMessage(
"Ignoring edge"
);
136
}
137
}
138
145
public
:
Vertex<V>
&
AddVertex
(
const
std::string
&
_name
,
146
const
V
&
_data
,
147
const
VertexId
&
_id
= kNullId)
148
{
149
auto
id
=
_id
;
150
151
// The user didn't provide an Id, we generate it.
152
if
(
id
==
kNullId
)
153
{
154
id
= this->NextVertexId();
155
156
// No space for new Ids.
157
if
(
id
==
kNullId
)
158
{
159
detail::LogErrorMessage(
160
"[Graph::AddVertex()] The limit of vertices has been reached. "
161
"Ignoring vertex."
);
162
return
NullVertex<V>
();
163
}
164
}
165
166
// Create the vertex.
167
auto
ret
= this->vertices.insert(
168
std::make_pair
(
id
,
Vertex<V>
(
_name
,
_data
,
id
)));
169
170
// The Id already exists.
171
if
(!
ret
.second)
172
{
173
std::ostringstream
errStream
;
174
errStream
<<
"[Graph::AddVertex()] Repeated vertex ["
<<
id
<<
"]"
;
175
detail::LogErrorMessage(
errStream
.str());
176
return
NullVertex<V>
();
177
}
178
179
// Link the vertex with an empty list of edges.
180
this->adjList[id] =
EdgeId_S
();
181
182
return
ret
.first->second;
183
}
184
188
public
:
const
VertexRef_M<V>
Vertices
()
const
189
{
190
VertexRef_M<V>
res
;
191
for
(
auto
const
&
v
: this->vertices)
192
res
.emplace(
std::make_pair
(
v
.first,
std::cref
(
v
.second)));
193
194
return
res
;
195
}
196
200
public
:
const
VertexRef_M<V>
Vertices
(
const
std::string
&
_name
)
const
201
{
202
VertexRef_M<V>
res
;
203
for
(
auto
const
&
vertex
: this->vertices)
204
{
205
if
(
vertex
.second.Name() ==
_name
)
206
res
.emplace(
std::make_pair
(
vertex
.first,
std::cref
(
vertex
.second)));
207
}
208
209
return
res
;
210
}
211
218
public
:
EdgeType
&
AddEdge
(
const
VertexId_P
&
_vertices
,
219
const
E
&
_data
,
220
const
double
_weight
= 1.0)
221
{
222
auto
id
= this->NextEdgeId();
223
224
// No space for new Ids.
225
if
(
id
==
kNullId
)
226
{
227
detail::LogErrorMessage(
228
"[Graph::AddEdge()] The limit of edges has been reached. "
229
"Ignoring edge."
);
230
return
NullEdge<E, EdgeType>
();
231
}
232
233
EdgeType
newEdge
(
_vertices
,
_data
,
_weight
,
id
);
234
return
this->LinkEdge(
std::move
(
newEdge
));
235
}
236
243
public
:
EdgeType
&
LinkEdge
(
const
EdgeType
&
_edge
)
244
{
245
auto
edgeVertices
=
_edge
.Vertices();
246
247
// Sanity check: Both vertices should exist.
248
for
(
auto
const
&
v
: {
edgeVertices
.first,
edgeVertices
.second})
249
{
250
if
(this->vertices.find(
v
) == this->vertices.end())
251
return
NullEdge<E, EdgeType>
();
252
}
253
254
// Link the new edge.
255
for
(
auto
const
&
v
: {
edgeVertices
.first,
edgeVertices
.second})
256
{
257
if
(
v
!=
kNullId
)
258
{
259
auto
vertexIt
= this->adjList.find(
v
);
260
assert
(
vertexIt
!= this->adjList.end());
261
vertexIt
->second.insert(
_edge
.Id());
262
}
263
}
264
265
auto
ret
= this->edges.insert(
std::make_pair
(
_edge
.Id(),
_edge
));
266
267
// Return the new edge.
268
return
ret
.first->second;
269
}
270
274
public
:
const
EdgeRef_M<EdgeType>
Edges
()
const
275
{
276
EdgeRef_M<EdgeType>
res
;
277
for
(
auto
const
&
edge
: this->edges)
278
{
279
res
.emplace(
std::make_pair
(
edge
.first,
std::cref
(
edge
.second)));
280
}
281
282
return
res
;
283
}
284
300
public
:
VertexRef_M<V>
AdjacentsFrom
(
const
VertexId
&
_vertex
)
const
301
{
302
VertexRef_M<V>
res
;
303
304
// Make sure the vertex exists
305
auto
vertexIt
= this->adjList.find(
_vertex
);
306
if
(
vertexIt
== this->adjList.end())
307
return
res
;
308
309
for
(
auto
const
&
edgeId
:
vertexIt
->second)
310
{
311
const
auto
&
edge
= this->EdgeFromId(
edgeId
);
312
auto
neighborVertexId
=
edge
.From(
_vertex
);
313
if
(
neighborVertexId
!=
kNullId
)
314
{
315
const
auto
&
neighborVertex
= this->VertexFromId(
neighborVertexId
);
316
res
.emplace(
317
std::make_pair
(
neighborVertexId
,
std::cref
(
neighborVertex
)));
318
}
319
}
320
321
return
res
;
322
}
323
339
public
:
VertexRef_M<V>
AdjacentsFrom
(
const
Vertex<V>
&
_vertex
)
const
340
{
341
return
this->AdjacentsFrom(
_vertex
.Id());
342
}
343
359
public
:
VertexRef_M<V>
AdjacentsTo
(
const
VertexId
&
_vertex
)
const
360
{
361
auto
incidentEdges
= this->IncidentsTo(
_vertex
);
362
363
VertexRef_M<V>
res
;
364
for
(
auto
const
&
incidentEdgeRef
:
incidentEdges
)
365
{
366
const
auto
&
incidentEdgeId
=
incidentEdgeRef
.first;
367
const
auto
&
incidentEdge
= this->EdgeFromId(
incidentEdgeId
);
368
const
auto
&
neighborVertexId
=
incidentEdge
.To(
_vertex
);
369
const
auto
&
neighborVertex
= this->VertexFromId(
neighborVertexId
);
370
res
.emplace(
371
std::make_pair
(
neighborVertexId
,
std::cref
(
neighborVertex
)));
372
}
373
374
return
res
;
375
}
376
392
public
:
VertexRef_M<V>
AdjacentsTo
(
const
Vertex<V>
&
_vertex
)
const
393
{
394
return
this->AdjacentsTo(
_vertex
.Id());
395
}
396
400
public
:
size_t
InDegree
(
const
VertexId
&
_vertex
)
const
401
{
402
return
this->IncidentsTo(
_vertex
).size();
403
}
404
408
public
:
size_t
InDegree
(
const
Vertex<V>
&
_vertex
)
const
409
{
410
return
this->IncidentsTo(this->VertexFromId(
_vertex
.Id())).size();
411
}
412
416
public
:
size_t
OutDegree
(
const
VertexId
&
_vertex
)
const
417
{
418
return
this->IncidentsFrom(
_vertex
).size();
419
}
420
424
public
:
size_t
OutDegree
(
const
Vertex<V>
&
_vertex
)
const
425
{
426
return
this->IncidentsFrom(this->VertexFromId(
_vertex
.Id())).size();
427
}
428
434
public
:
const
EdgeRef_M<EdgeType>
IncidentsFrom
(
const
VertexId
&
_vertex
)
435
const
436
{
437
EdgeRef_M<EdgeType>
res
;
438
439
const
auto
&
adjIt
= this->adjList.find(
_vertex
);
440
if
(
adjIt
== this->adjList.end())
441
return
res
;
442
443
const
auto
&
edgeIds
=
adjIt
->second;
444
for
(
auto
const
&
edgeId
:
edgeIds
)
445
{
446
const
auto
&
edge
= this->EdgeFromId(
edgeId
);
447
if
(
edge
.From(
_vertex
) !=
kNullId
)
448
res
.emplace(
std::make_pair
(
edge
.Id(),
std::cref
(
edge
)));
449
}
450
451
return
res
;
452
}
453
459
public
:
const
EdgeRef_M<EdgeType>
IncidentsFrom
(
460
const
Vertex<V>
&
_vertex
)
const
461
{
462
return
this->IncidentsFrom(
_vertex
.Id());
463
}
464
470
public
:
const
EdgeRef_M<EdgeType>
IncidentsTo
(
471
const
VertexId
&
_vertex
)
const
472
{
473
EdgeRef_M<EdgeType>
res
;
474
475
const
auto
&
adjIt
= this->adjList.find(
_vertex
);
476
if
(
adjIt
== this->adjList.end())
477
return
res
;
478
479
const
auto
&
edgeIds
=
adjIt
->second;
480
for
(
auto
const
&
edgeId
:
edgeIds
)
481
{
482
const
auto
&
edge
= this->EdgeFromId(
edgeId
);
483
if
(
edge
.To(
_vertex
) !=
kNullId
)
484
res
.emplace(
std::make_pair
(
edge
.Id(),
std::cref
(
edge
)));
485
}
486
487
return
res
;
488
}
489
495
public
:
const
EdgeRef_M<EdgeType>
IncidentsTo
(
const
Vertex<V>
&
_vertex
)
496
const
497
{
498
return
this->IncidentsTo(
_vertex
.Id());
499
}
500
504
public
:
bool
Empty
()
const
505
{
506
return
this->vertices.empty();
507
}
508
512
public
:
bool
RemoveVertex
(
const
VertexId
&
_vertex
)
513
{
514
auto
vIt
= this->vertices.find(
_vertex
);
515
if
(
vIt
== this->vertices.end())
516
return
false
;
517
518
// Remove incident edges.
519
auto
incidents
= this->IncidentsTo(
_vertex
);
520
for
(
auto
edgePair
:
incidents
)
521
this->RemoveEdge(
edgePair
.first);
522
523
// Remove all outgoing edges.
524
incidents
= this->IncidentsFrom(
_vertex
);
525
for
(
auto
edgePair
:
incidents
)
526
this->RemoveEdge(
edgePair
.first);
527
528
// Remove the vertex (key) from the adjacency list.
529
this->adjList.erase(
_vertex
);
530
531
// Remove the vertex.
532
this->vertices.erase(
_vertex
);
533
534
return
true
;
535
}
536
540
public
:
bool
RemoveVertex
(
Vertex<V>
&
_vertex
)
541
{
542
return
this->RemoveVertex(
_vertex
.Id());
543
}
544
548
public
:
size_t
RemoveVertices
(
const
std::string
&
_name
)
549
{
550
std::vector<VertexId>
toRemove
;
551
for
(
auto
const
&[
id
,
vertex
] : this->vertices)
552
{
553
if
(
vertex
.Name() ==
_name
)
554
toRemove
.push_back(
id
);
555
}
556
557
size_t
result
= 0;
558
for
(
auto
const
&
id
:
toRemove
)
559
{
560
if
(this->RemoveVertex(
id
))
561
++
result
;
562
}
563
return
result
;
564
}
565
571
public
:
bool
RemoveEdge
(
const
EdgeId
&
_edge
)
572
{
573
auto
edgeIt
= this->edges.find(
_edge
);
574
if
(
edgeIt
== this->edges.end())
575
return
false
;
576
577
auto
edgeVertices
=
edgeIt
->second.Vertices();
578
579
// Unlink the edge.
580
for
(
auto
const
&
v
: {
edgeVertices
.first,
edgeVertices
.second})
581
{
582
if
(
edgeIt
->second.From(
v
) !=
kNullId
)
583
{
584
auto
vertex
= this->adjList.find(
v
);
585
assert
(
vertex
!= this->adjList.end());
586
vertex
->second.erase(
_edge
);
587
}
588
}
589
590
this->edges.erase(
_edge
);
591
592
return
true
;
593
}
594
600
public
:
bool
RemoveEdge
(
EdgeType
&
_edge
)
601
{
602
return
this->RemoveEdge(
_edge
.Id());
603
}
604
609
public
:
const
Vertex<V>
&
VertexFromId
(
const
VertexId
&
_id
)
const
610
{
611
auto
iter = this->vertices.find(
_id
);
612
if
(iter == this->vertices.end())
613
return
NullVertex<V>
();
614
615
return
iter->second;
616
}
617
622
public
:
Vertex<V>
&
VertexFromId
(
const
VertexId
&
_id
)
623
{
624
auto
iter = this->vertices.find(
_id
);
625
if
(iter == this->vertices.end())
626
return
NullVertex<V>
();
627
628
return
iter->second;
629
}
630
639
public
:
const
EdgeType
&
EdgeFromVertices
(
640
const
VertexId
_sourceId
,
const
VertexId
_destId
)
const
641
{
642
// Get the adjacency iterator for the source vertex.
643
const
typename
std::map<VertexId, EdgeId_S>::const_iterator
&
adjIt
=
644
this->adjList.find(
_sourceId
);
645
646
// Quit early if there is no adjacency entry
647
if
(
adjIt
== this->adjList.end())
648
return
NullEdge<E, EdgeType>
();
649
650
// Loop over the edges in the source vertex's adjacency list
651
for
(
std::set<EdgeId>::const_iterator
edgIt
=
adjIt
->second.begin();
652
edgIt
!=
adjIt
->second.end(); ++
edgIt
)
653
{
654
// Get an iterator to the actual edge
655
const
typename
std::map<EdgeId, EdgeType>::const_iterator
edgeIter
=
656
this->edges.find(*
edgIt
);
657
658
// Check if the edge has the correct source and destination.
659
if
(
edgeIter
!= this->edges.end() &&
660
edgeIter
->second.From(
_sourceId
) ==
_destId
)
661
{
662
assert
(
edgeIter
->second.To(
_destId
) ==
_sourceId
);
663
return
edgeIter
->second;
664
}
665
}
666
667
return
NullEdge<E, EdgeType>
();
668
}
669
674
public
:
const
EdgeType
&
EdgeFromId
(
const
EdgeId
&
_id
)
const
675
{
676
auto
iter = this->edges.find(
_id
);
677
if
(iter == this->edges.end())
678
return
NullEdge<E, EdgeType>
();
679
680
return
iter->second;
681
}
682
687
public
:
EdgeType
&
EdgeFromId
(
const
EdgeId
&
_id
)
688
{
689
auto
iter = this->edges.find(
_id
);
690
if
(iter == this->edges.end())
691
return
NullEdge<E, EdgeType>
();
692
693
return
iter->second;
694
}
695
701
public
:
template
<
typename
VV,
typename
EE,
typename
EEdgeType>
702
friend
std::ostream
&
operator<<
(
std::ostream
&
_out
,
703
const
Graph<VV, EE, EEdgeType>
&
_g
);
704
707
private
:
VertexId
&NextVertexId()
708
{
709
while
(this->vertices.find(
this
->nextVertexId) !=
this
->vertices.end()
710
&&
this
->nextVertexId < MAX_UI64)
711
{
712
++this->nextVertexId;
713
}
714
715
return
this->nextVertexId;
716
}
717
720
private
: VertexId &NextEdgeId()
721
{
722
while
(this->edges.find(
this
->nextEdgeId) !=
this
->edges.end() &&
723
this
->nextEdgeId < MAX_UI64)
724
{
725
++this->nextEdgeId;
726
}
727
728
return
this->nextEdgeId;
729
}
730
732
protected
:
VertexId
nextVertexId = 0
u
;
733
735
protected
:
VertexId
nextEdgeId = 0
u
;
736
738
private
:
std::map<VertexId, Vertex<V>
> vertices;
739
741
private
:
std::map<EdgeId, EdgeType>
edges;
742
748
private
:
std::map<VertexId, EdgeId_S>
adjList;
749
753
private
:
std::multimap<std::string, VertexId>
names;
754
};
755
758
template
<
typename
VV,
typename
EE>
759
std::ostream
&
operator<<
(
std::ostream
&
_out
,
760
const
Graph
<
VV
,
EE
,
UndirectedEdge<EE>
> &
_g
)
761
{
762
_out
<<
"graph {"
<<
std::endl
;
763
764
// All vertices with the name and Id as a "label" attribute.
765
for
(
auto
const
&
vertexMap
:
_g
.Vertices())
766
{
767
auto
vertex
=
vertexMap
.second.get();
768
_out
<<
vertex
;
769
}
770
771
// All edges.
772
for
(
auto
const
&
edgeMap
:
_g
.Edges())
773
{
774
auto
edge
=
edgeMap
.second.get();
775
_out
<<
edge
;
776
}
777
778
_out
<<
"}"
<<
std::endl
;
779
780
return
_out
;
781
}
782
785
template
<
typename
VV,
typename
EE>
786
std::ostream
&
operator<<
(
std::ostream
&
_out
,
787
const
Graph
<
VV
,
EE
,
DirectedEdge<EE>
> &
_g
)
788
{
789
_out
<<
"digraph {"
<<
std::endl
;
790
791
// All vertices with the name and Id as a "label" attribute.
792
for
(
auto
const
&
vertexMap
:
_g
.Vertices())
793
{
794
auto
vertex
=
vertexMap
.second.get();
795
_out
<<
vertex
;
796
}
797
798
// All edges.
799
for
(
auto
const
&
edgeMap
:
_g
.Edges())
800
{
801
auto
edge
=
edgeMap
.second.get();
802
_out
<<
edge
;
803
}
804
805
_out
<<
"}"
<<
std::endl
;
806
807
return
_out
;
808
}
809
812
template
<
typename
V,
typename
E>
813
using
UndirectedGraph
=
Graph<V, E, UndirectedEdge<E>
>;
814
817
template
<
typename
V,
typename
E>
818
using
DirectedGraph
=
Graph<V, E, DirectedEdge<E>
>;
819
}
// namespace graph
820
}
// namespace GZ_MATH_VERSION_NAMESPACE
821
}
// namespace gz::math::graph
822
#endif
// GZ_MATH_GRAPH_GRAPH_HH_