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"
33
34namespace gz::math
35{
36// Inline bracket to help doxygen filtering.
37inline namespace GZ_MATH_VERSION_NAMESPACE {
38namespace graph
39{
48 //
101 template<typename V, typename E, typename EdgeType>
102 class Graph
103 {
105 public: Graph() = default;
106
112 {
113 // Add all vertices.
114 for (auto const &v : _vertices)
115 {
116 if (!this->AddVertex(v.Name(), v.Data(), v.Id()).Valid())
117 {
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
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(
162
163 // The Id already exists.
164 if (!ret.second)
165 {
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 {
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 {
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
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
230 return this->LinkEdge(std::move(newEdge));
231 }
232
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 {
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
297 {
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);
310 {
311 const auto &neighborVertex = this->VertexFromId(neighborVertexId);
312 res.emplace(
314 }
315 }
316
317 return res;
318 }
319
336 {
337 return this->AdjacentsFrom(_vertex.Id());
338 }
339
356 {
357 auto incidentEdges = this->IncidentsTo(_vertex);
358
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(
368 }
369
370 return res;
371 }
372
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
431 const
432 {
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
456 const Vertex<V> &_vertex) const
457 {
458 return this->IncidentsFrom(_vertex.Id());
459 }
460
467 const VertexId &_vertex) const
468 {
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
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
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
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
645 const VertexId _sourceId, const VertexId _destId) const
646 {
647 // Get the adjacency iterator for the source vertex.
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
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>
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 = 0u;
738
740 protected: VertexId nextEdgeId = 0u;
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
757 };
758
761 template<typename VV, typename EE>
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>
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>
817
820 template<typename V, typename E>
822} // namespace graph
823} // namespace GZ_MATH_VERSION_NAMESPACE
824} // namespace gz::math::graph
825#endif // GZ_MATH_GRAPH_GRAPH_HH_