Gazebo Math

API Reference

7.6.0
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 <iostream>
22 #include <iterator>
23 #include <map>
24 #include <set>
25 #include <string>
26 #include <utility>
27 #include <vector>
28 
29 #include <gz/math/config.hh>
30 #include "gz/math/graph/Edge.hh"
31 #include "gz/math/graph/Vertex.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 {
53  //
106  template<typename V, typename E, typename EdgeType>
107  class Graph
108  {
110  public: Graph() = default;
111 
115  public: Graph(const std::vector<Vertex<V>> &_vertices,
116  const std::vector<EdgeInitializer<E>> &_edges)
117  {
118  // Add all vertices.
119  for (auto const &v : _vertices)
120  {
121  if (!this->AddVertex(v.Name(), v.Data(), v.Id()).Valid())
122  {
123  std::cerr << "Invalid vertex with Id [" << v.Id() << "]. Ignoring."
124  << std::endl;
125  }
126  }
127 
128  // Add all edges.
129  for (auto const &e : _edges)
130  {
131  if (!this->AddEdge(e.vertices, e.data, e.weight).Valid())
132  std::cerr << "Ignoring edge" << std::endl;
133  }
134  }
135 
142  public: Vertex<V> &AddVertex(const std::string &_name,
143  const V &_data,
144  const VertexId &_id = kNullId)
145  {
146  auto id = _id;
147 
148  // The user didn't provide an Id, we generate it.
149  if (id == kNullId)
150  {
151  id = this->NextVertexId();
152 
153  // No space for new Ids.
154  if (id == kNullId)
155  {
156  std::cerr << "[Graph::AddVertex()] The limit of vertices has been "
157  << "reached. Ignoring vertex." << std::endl;
158  return Vertex<V>::NullVertex;
159  }
160  }
161 
162  // Create the vertex.
163  auto ret = this->vertices.insert(
164  std::make_pair(id, Vertex<V>(_name, _data, id)));
165 
166  // The Id already exists.
167  if (!ret.second)
168  {
169  std::cerr << "[Graph::AddVertex()] Repeated vertex [" << id << "]"
170  << std::endl;
171  return Vertex<V>::NullVertex;
172  }
173 
174  // Link the vertex with an empty list of edges.
175  this->adjList[id] = EdgeId_S();
176 
177  return ret.first->second;
178  }
179 
183  public: const VertexRef_M<V> Vertices() const
184  {
185  VertexRef_M<V> res;
186  for (auto const &v : this->vertices)
187  res.emplace(std::make_pair(v.first, std::cref(v.second)));
188 
189  return res;
190  }
191 
195  public: const VertexRef_M<V> Vertices(const std::string &_name) const
196  {
197  VertexRef_M<V> res;
198  for (auto const &vertex : this->vertices)
199  {
200  if (vertex.second.Name() == _name)
201  res.emplace(std::make_pair(vertex.first, std::cref(vertex.second)));
202  }
203 
204  return res;
205  }
206 
213  public: EdgeType &AddEdge(const VertexId_P &_vertices,
214  const E &_data,
215  const double _weight = 1.0)
216  {
217  auto id = this->NextEdgeId();
218 
219  // No space for new Ids.
220  if (id == kNullId)
221  {
222  std::cerr << "[Graph::AddEdge()] The limit of edges has been reached. "
223  << "Ignoring edge." << std::endl;
224  return EdgeType::NullEdge;
225  }
226 
227  EdgeType newEdge(_vertices, _data, _weight, id);
228  return this->LinkEdge(std::move(newEdge));
229  }
230 
237  public: EdgeType &LinkEdge(const EdgeType &_edge)
238  {
239  auto edgeVertices = _edge.Vertices();
240 
241  // Sanity check: Both vertices should exist.
242  for (auto const &v : {edgeVertices.first, edgeVertices.second})
243  {
244  if (this->vertices.find(v) == this->vertices.end())
245  return EdgeType::NullEdge;
246  }
247 
248  // Link the new edge.
249  for (auto const &v : {edgeVertices.first, edgeVertices.second})
250  {
251  if (v != kNullId)
252  {
253  auto vertexIt = this->adjList.find(v);
254  assert(vertexIt != this->adjList.end());
255  vertexIt->second.insert(_edge.Id());
256  }
257  }
258 
259  auto ret = this->edges.insert(std::make_pair(_edge.Id(), _edge));
260 
261  // Return the new edge.
262  return ret.first->second;
263  }
264 
268  public: const EdgeRef_M<EdgeType> Edges() const
269  {
271  for (auto const &edge : this->edges)
272  {
273  res.emplace(std::make_pair(edge.first, std::cref(edge.second)));
274  }
275 
276  return res;
277  }
278 
294  public: VertexRef_M<V> AdjacentsFrom(const VertexId &_vertex) const
295  {
296  VertexRef_M<V> res;
297 
298  // Make sure the vertex exists
299  auto vertexIt = this->adjList.find(_vertex);
300  if (vertexIt == this->adjList.end())
301  return res;
302 
303  for (auto const &edgeId : vertexIt->second)
304  {
305  const auto &edge = this->EdgeFromId(edgeId);
306  auto neighborVertexId = edge.From(_vertex);
307  if (neighborVertexId != kNullId)
308  {
309  const auto &neighborVertex = this->VertexFromId(neighborVertexId);
310  res.emplace(
311  std::make_pair(neighborVertexId, std::cref(neighborVertex)));
312  }
313  }
314 
315  return res;
316  }
317 
333  public: VertexRef_M<V> AdjacentsFrom(const Vertex<V> &_vertex) const
334  {
335  return this->AdjacentsFrom(_vertex.Id());
336  }
337 
353  public: VertexRef_M<V> AdjacentsTo(const VertexId &_vertex) const
354  {
355  auto incidentEdges = this->IncidentsTo(_vertex);
356 
357  VertexRef_M<V> res;
358  for (auto const &incidentEdgeRef : incidentEdges)
359  {
360  const auto &incidentEdgeId = incidentEdgeRef.first;
361  const auto &incidentEdge = this->EdgeFromId(incidentEdgeId);
362  const auto &neighborVertexId = incidentEdge.To(_vertex);
363  const auto &neighborVertex = this->VertexFromId(neighborVertexId);
364  res.emplace(
365  std::make_pair(neighborVertexId, std::cref(neighborVertex)));
366  }
367 
368  return res;
369  }
370 
386  public: VertexRef_M<V> AdjacentsTo(const Vertex<V> &_vertex) const
387  {
388  return this->AdjacentsTo(_vertex.Id());
389  }
390 
394  public: size_t InDegree(const VertexId &_vertex) const
395  {
396  return this->IncidentsTo(_vertex).size();
397  }
398 
402  public: size_t InDegree(const Vertex<V> &_vertex) const
403  {
404  return this->IncidentsTo(this->VertexFromId(_vertex.Id())).size();
405  }
406 
410  public: size_t OutDegree(const VertexId &_vertex) const
411  {
412  return this->IncidentsFrom(_vertex).size();
413  }
414 
418  public: size_t OutDegree(const Vertex<V> &_vertex) const
419  {
420  return this->IncidentsFrom(this->VertexFromId(_vertex.Id())).size();
421  }
422 
428  public: const EdgeRef_M<EdgeType> IncidentsFrom(const VertexId &_vertex)
429  const
430  {
432 
433  const auto &adjIt = this->adjList.find(_vertex);
434  if (adjIt == this->adjList.end())
435  return res;
436 
437  const auto &edgeIds = adjIt->second;
438  for (auto const &edgeId : edgeIds)
439  {
440  const auto &edge = this->EdgeFromId(edgeId);
441  if (edge.From(_vertex) != kNullId)
442  res.emplace(std::make_pair(edge.Id(), std::cref(edge)));
443  }
444 
445  return res;
446  }
447 
454  const Vertex<V> &_vertex) const
455  {
456  return this->IncidentsFrom(_vertex.Id());
457  }
458 
465  const VertexId &_vertex) const
466  {
468 
469  const auto &adjIt = this->adjList.find(_vertex);
470  if (adjIt == this->adjList.end())
471  return res;
472 
473  const auto &edgeIds = adjIt->second;
474  for (auto const &edgeId : edgeIds)
475  {
476  const auto &edge = this->EdgeFromId(edgeId);
477  if (edge.To(_vertex) != kNullId)
478  res.emplace(std::make_pair(edge.Id(), std::cref(edge)));
479  }
480 
481  return res;
482  }
483 
489  public: const EdgeRef_M<EdgeType> IncidentsTo(const Vertex<V> &_vertex)
490  const
491  {
492  return this->IncidentsTo(_vertex.Id());
493  }
494 
498  public: bool Empty() const
499  {
500  return this->vertices.empty();
501  }
502 
506  public: bool RemoveVertex(const VertexId &_vertex)
507  {
508  auto vIt = this->vertices.find(_vertex);
509  if (vIt == this->vertices.end())
510  return false;
511 
512  // Remove incident edges.
513  auto incidents = this->IncidentsTo(_vertex);
514  for (auto edgePair : incidents)
515  this->RemoveEdge(edgePair.first);
516 
517  // Remove all outgoing edges.
518  incidents = this->IncidentsFrom(_vertex);
519  for (auto edgePair : incidents)
520  this->RemoveEdge(edgePair.first);
521 
522  // Remove the vertex (key) from the adjacency list.
523  this->adjList.erase(_vertex);
524 
525  // Remove the vertex.
526  this->vertices.erase(_vertex);
527 
528  return true;
529  }
530 
534  public: bool RemoveVertex(Vertex<V> &_vertex)
535  {
536  return this->RemoveVertex(_vertex.Id());
537  }
538 
542  public: size_t RemoveVertices(const std::string &_name)
543  {
544  std::vector<VertexId> toRemove;
545  for (auto const &[id, vertex] : this->vertices)
546  {
547  if (vertex.Name() == _name)
548  toRemove.push_back(id);
549  }
550 
551  size_t result = 0;
552  for (auto const &id : toRemove)
553  {
554  if (this->RemoveVertex(id))
555  ++result;
556  }
557  return result;
558  }
559 
565  public: bool RemoveEdge(const EdgeId &_edge)
566  {
567  auto edgeIt = this->edges.find(_edge);
568  if (edgeIt == this->edges.end())
569  return false;
570 
571  auto edgeVertices = edgeIt->second.Vertices();
572 
573  // Unlink the edge.
574  for (auto const &v : {edgeVertices.first, edgeVertices.second})
575  {
576  if (edgeIt->second.From(v) != kNullId)
577  {
578  auto vertex = this->adjList.find(v);
579  assert(vertex != this->adjList.end());
580  vertex->second.erase(_edge);
581  }
582  }
583 
584  this->edges.erase(_edge);
585 
586  return true;
587  }
588 
594  public: bool RemoveEdge(EdgeType &_edge)
595  {
596  return this->RemoveEdge(_edge.Id());
597  }
598 
603  public: const Vertex<V> &VertexFromId(const VertexId &_id) const
604  {
605  auto iter = this->vertices.find(_id);
606  if (iter == this->vertices.end())
607  return Vertex<V>::NullVertex;
608 
609  return iter->second;
610  }
611 
616  public: Vertex<V> &VertexFromId(const VertexId &_id)
617  {
618  auto iter = this->vertices.find(_id);
619  if (iter == this->vertices.end())
620  return Vertex<V>::NullVertex;
621 
622  return iter->second;
623  }
624 
633  public: const EdgeType &EdgeFromVertices(
634  const VertexId _sourceId, const VertexId _destId) const
635  {
636  // Get the adjacency iterator for the source vertex.
637  const typename std::map<VertexId, EdgeId_S>::const_iterator &adjIt =
638  this->adjList.find(_sourceId);
639 
640  // Quit early if there is no adjacency entry
641  if (adjIt == this->adjList.end())
642  return EdgeType::NullEdge;
643 
644  // Loop over the edges in the source vertex's adjacency list
645  for (std::set<EdgeId>::const_iterator edgIt = adjIt->second.begin();
646  edgIt != adjIt->second.end(); ++edgIt)
647  {
648  // Get an iterator to the actual edge
649  const typename std::map<EdgeId, EdgeType>::const_iterator edgeIter =
650  this->edges.find(*edgIt);
651 
652  // Check if the edge has the correct source and destination.
653  if (edgeIter != this->edges.end() &&
654  edgeIter->second.From(_sourceId) == _destId)
655  {
656  assert(edgeIter->second.To(_destId) == _sourceId);
657  return edgeIter->second;
658  }
659  }
660 
661  return EdgeType::NullEdge;
662  }
663 
668  public: const EdgeType &EdgeFromId(const EdgeId &_id) const
669  {
670  auto iter = this->edges.find(_id);
671  if (iter == this->edges.end())
672  return EdgeType::NullEdge;
673 
674  return iter->second;
675  }
676 
681  public: EdgeType &EdgeFromId(const EdgeId &_id)
682  {
683  auto iter = this->edges.find(_id);
684  if (iter == this->edges.end())
685  return EdgeType::NullEdge;
686 
687  return iter->second;
688  }
689 
695  public: template<typename VV, typename EE, typename EEdgeType>
697  const Graph<VV, EE, EEdgeType> &_g);
698 
701  private: VertexId &NextVertexId()
702  {
703  while (this->vertices.find(this->nextVertexId) != this->vertices.end()
704  && this->nextVertexId < MAX_UI64)
705  {
706  ++this->nextVertexId;
707  }
708 
709  return this->nextVertexId;
710  }
711 
714  private: VertexId &NextEdgeId()
715  {
716  while (this->edges.find(this->nextEdgeId) != this->edges.end() &&
717  this->nextEdgeId < MAX_UI64)
718  {
719  ++this->nextEdgeId;
720  }
721 
722  return this->nextEdgeId;
723  }
724 
726  protected: VertexId nextVertexId = 0u;
727 
729  protected: VertexId nextEdgeId = 0u;
730 
732  private: std::map<VertexId, Vertex<V>> vertices;
733 
735  private: std::map<EdgeId, EdgeType> edges;
736 
742  private: std::map<VertexId, EdgeId_S> adjList;
743 
748  };
749 
752  template<typename VV, typename EE>
754  const Graph<VV, EE, UndirectedEdge<EE>> &_g)
755  {
756  _out << "graph {" << std::endl;
757 
758  // All vertices with the name and Id as a "label" attribute.
759  for (auto const &vertexMap : _g.Vertices())
760  {
761  auto vertex = vertexMap.second.get();
762  _out << vertex;
763  }
764 
765  // All edges.
766  for (auto const &edgeMap : _g.Edges())
767  {
768  auto edge = edgeMap.second.get();
769  _out << edge;
770  }
771 
772  _out << "}" << std::endl;
773 
774  return _out;
775  }
776 
779  template<typename VV, typename EE>
781  const Graph<VV, EE, DirectedEdge<EE>> &_g)
782  {
783  _out << "digraph {" << std::endl;
784 
785  // All vertices with the name and Id as a "label" attribute.
786  for (auto const &vertexMap : _g.Vertices())
787  {
788  auto vertex = vertexMap.second.get();
789  _out << vertex;
790  }
791 
792  // All edges.
793  for (auto const &edgeMap : _g.Edges())
794  {
795  auto edge = edgeMap.second.get();
796  _out << edge;
797  }
798 
799  _out << "}" << std::endl;
800 
801  return _out;
802  }
803 
806  template<typename V, typename E>
808 
811  template<typename V, typename E>
813 } // namespace graph
814 } // namespace GZ_MATH_VERSION_NAMESPACE
815 } // namespace gz::math::graph
816 #endif // GZ_MATH_GRAPH_GRAPH_HH_