Gazebo Math

API Reference

9.2.0
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"
34
35namespace gz::math
36{
37// Inline bracket to help doxygen filtering.
38inline namespace GZ_MATH_VERSION_NAMESPACE {
39namespace graph
40{
55 //
108 template<typename V, typename E, typename EdgeType>
109 class Graph
110 {
112 public: Graph() = default;
113
119 {
120 // Add all vertices.
121 for (auto const &v : _vertices)
122 {
123 if (!this->AddVertex(v.Name(), v.Data(), v.Id()).Valid())
124 {
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
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(
169
170 // The Id already exists.
171 if (!ret.second)
172 {
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 {
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 {
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
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
234 return this->LinkEdge(std::move(newEdge));
235 }
236
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 {
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
301 {
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);
314 {
315 const auto &neighborVertex = this->VertexFromId(neighborVertexId);
316 res.emplace(
318 }
319 }
320
321 return res;
322 }
323
340 {
341 return this->AdjacentsFrom(_vertex.Id());
342 }
343
360 {
361 auto incidentEdges = this->IncidentsTo(_vertex);
362
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(
372 }
373
374 return res;
375 }
376
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
435 const
436 {
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
460 const Vertex<V> &_vertex) const
461 {
462 return this->IncidentsFrom(_vertex.Id());
463 }
464
471 const VertexId &_vertex) const
472 {
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
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
541 {
542 return this->RemoveVertex(_vertex.Id());
543 }
544
548 public: size_t RemoveVertices(const std::string &_name)
549 {
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
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
640 const VertexId _sourceId, const VertexId _destId) const
641 {
642 // Get the adjacency iterator for the source vertex.
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
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>
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 = 0u;
733
735 protected: VertexId nextEdgeId = 0u;
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
754 };
755
758 template<typename VV, typename EE>
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>
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>
814
817 template<typename V, typename E>
819} // namespace graph
820} // namespace GZ_MATH_VERSION_NAMESPACE
821} // namespace gz::math::graph
822#endif // GZ_MATH_GRAPH_GRAPH_HH_