andres::graph
graph.hxx
1 #pragma once
2 #ifndef ANDRES_GRAPH_HXX
3 #define ANDRES_GRAPH_HXX
4 
5 #include <cassert>
6 #include <cstddef>
7 #include <iterator> // std::random_access_iterator
8 #include <vector>
9 #include <set>
10 #include <iostream>
11 #include <utility> // std::pair
12 #include <algorithm> // std::fill
13 
14 #include "adjacency.hxx"
15 #include "subgraph.hxx"
16 #include "visitor.hxx"
17 #include "detail/graph.hxx"
18 
20 namespace andres {
21 
23 namespace graph {
24 
26 template<typename VISITOR = IdleGraphVisitor<std::size_t> >
27 class Graph {
28 public:
29  typedef VISITOR Visitor;
30  typedef detail::VertexIterator VertexIterator;
31  typedef detail::EdgeIterator EdgeIterator;
32  typedef detail::Adjacencies::const_iterator AdjacencyIterator;
33  typedef typename AdjacencyIterator::value_type AdjacencyType;
34 
35  // construction
36  Graph(const Visitor& = Visitor());
37  Graph(const std::size_t, const Visitor& = Visitor());
38  void assign(const Visitor& = Visitor());
39  void assign(const std::size_t, const Visitor& = Visitor());
40  void reserveVertices(const std::size_t);
41  void reserveEdges(const std::size_t);
42 
43  // iterator access (compatible with Digraph)
44  VertexIterator verticesFromVertexBegin(const std::size_t) const;
45  VertexIterator verticesFromVertexEnd(const std::size_t) const;
46  VertexIterator verticesToVertexBegin(const std::size_t) const;
47  VertexIterator verticesToVertexEnd(const std::size_t) const;
48  EdgeIterator edgesFromVertexBegin(const std::size_t) const;
49  EdgeIterator edgesFromVertexEnd(const std::size_t) const;
50  EdgeIterator edgesToVertexBegin(const std::size_t) const;
51  EdgeIterator edgesToVertexEnd(const std::size_t) const;
52  AdjacencyIterator adjacenciesFromVertexBegin(const std::size_t) const;
53  AdjacencyIterator adjacenciesFromVertexEnd(const std::size_t) const;
54  AdjacencyIterator adjacenciesToVertexBegin(const std::size_t) const;
55  AdjacencyIterator adjacenciesToVertexEnd(const std::size_t) const;
56 
57  // access (compatible with Digraph)
58  std::size_t numberOfVertices() const;
59  std::size_t numberOfEdges() const;
60  std::size_t numberOfEdgesFromVertex(const std::size_t) const;
61  std::size_t numberOfEdgesToVertex(const std::size_t) const;
62  std::size_t vertexOfEdge(const std::size_t, const std::size_t) const;
63  std::size_t edgeFromVertex(const std::size_t, const std::size_t) const;
64  std::size_t edgeToVertex(const std::size_t, const std::size_t) const;
65  std::size_t vertexFromVertex(const std::size_t, const std::size_t) const;
66  std::size_t vertexToVertex(const std::size_t, const std::size_t) const;
67  const AdjacencyType& adjacencyFromVertex(const std::size_t, const std::size_t) const;
68  const AdjacencyType& adjacencyToVertex(const std::size_t, const std::size_t) const;
69  std::pair<bool, std::size_t> findEdge(const std::size_t, const std::size_t) const;
70  bool multipleEdgesEnabled() const;
71 
72  // manipulation
73  std::size_t insertVertex();
74  std::size_t insertVertices(const std::size_t);
75  std::size_t insertEdge(const std::size_t, const std::size_t);
76  void eraseVertex(const std::size_t);
77  void eraseEdge(const std::size_t);
78  bool& multipleEdgesEnabled();
79 
80 private:
81  typedef detail::Adjacencies Vertex;
82  typedef detail::Edge<false> Edge;
83 
84  void insertAdjacenciesForEdge(const std::size_t);
85  void eraseAdjacenciesForEdge(const std::size_t);
86 
87  std::vector<Vertex> vertices_;
88  std::vector<Edge> edges_;
89  bool multipleEdgesEnabled_;
90  Visitor visitor_;
91 };
92 
97 template<typename VISITOR>
98 inline
100  const Visitor& visitor
101 )
102 : vertices_(),
103  edges_(),
104  multipleEdgesEnabled_(false),
105  visitor_(visitor)
106 {}
107 
113 template<typename VISITOR>
114 inline
116  const std::size_t numberOfVertices,
117  const Visitor& visitor
118 )
119 : vertices_(numberOfVertices),
120  edges_(),
121  multipleEdgesEnabled_(false),
122  visitor_(visitor)
123 {
124  visitor_.insertVertices(0, numberOfVertices);
125 }
126 
131 template<typename VISITOR>
132 inline void
134  const Visitor& visitor
135 ) {
136  vertices_.clear();
137  edges_.clear();
138  multipleEdgesEnabled_ = false;
139  visitor_ = visitor;
140 }
141 
147 template<typename VISITOR>
148 inline void
150  const std::size_t numberOfVertices,
151  const Visitor& visitor
152 ) {
153  vertices_.resize(numberOfVertices);
154  std::fill(vertices_.begin(), vertices_.end(), Vertex());
155  edges_.clear();
156  multipleEdgesEnabled_ = false;
157  visitor_ = visitor;
158  visitor_.insertVertices(0, numberOfVertices);
159 }
160 
163 template<typename VISITOR>
164 inline std::size_t
166  return vertices_.size();
167 }
168 
171 template<typename VISITOR>
172 inline std::size_t
174  return edges_.size();
175 }
176 
183 template<typename VISITOR>
184 inline std::size_t
186  const std::size_t vertex
187 ) const {
188  return vertices_[vertex].size();
189 }
190 
197 template<typename VISITOR>
198 inline std::size_t
200  const std::size_t vertex
201 ) const {
202  return vertices_[vertex].size();
203 }
204 
210 template<typename VISITOR>
211 inline std::size_t
213  const std::size_t edge,
214  const std::size_t j
215 ) const {
216  assert(j < 2);
217 
218  return edges_[edge][j];
219 }
220 
228 template<typename VISITOR>
229 inline std::size_t
231  const std::size_t vertex,
232  const std::size_t j
233 ) const {
234  return vertices_[vertex][j].edge();
235 }
236 
244 template<typename VISITOR>
245 inline std::size_t
247  const std::size_t vertex,
248  const std::size_t j
249 ) const {
250  return vertices_[vertex][j].edge();
251 }
252 
260 template<typename VISITOR>
261 inline std::size_t
263  const std::size_t vertex,
264  const std::size_t j
265 ) const {
266  return vertices_[vertex][j].vertex();
267 }
268 
276 template<typename VISITOR>
277 inline std::size_t
279  const std::size_t vertex,
280  const std::size_t j
281 ) const {
282  return vertices_[vertex][j].vertex();
283 }
284 
291 template<typename VISITOR>
292 inline std::size_t
294  vertices_.push_back(Vertex());
295  visitor_.insertVertex(vertices_.size() - 1);
296  return vertices_.size() - 1;
297 }
298 
306 template<typename VISITOR>
307 inline std::size_t
309  const std::size_t number
310 ) {
311  std::size_t position = vertices_.size();
312  vertices_.insert(vertices_.end(), number, Vertex());
313  visitor_.insertVertices(position, number);
314  return position;
315 }
316 
323 template<typename VISITOR>
324 inline std::size_t
326  const std::size_t vertexIndex0,
327  const std::size_t vertexIndex1
328 ) {
329  assert(vertexIndex0 < numberOfVertices());
330  assert(vertexIndex1 < numberOfVertices());
331 
332  if(multipleEdgesEnabled()) {
333 insertEdgeMark:
334  edges_.push_back(Edge(vertexIndex0, vertexIndex1));
335  std::size_t edgeIndex = edges_.size() - 1;
336  insertAdjacenciesForEdge(edgeIndex);
337  visitor_.insertEdge(edgeIndex);
338  return edgeIndex;
339  }
340  else {
341  std::pair<bool, std::size_t> p = findEdge(vertexIndex0, vertexIndex1);
342  if(p.first) { // edge already exists
343  return p.second;
344  }
345  else {
346  goto insertEdgeMark;
347  }
348  }
349 }
350 
355 template<typename VISITOR>
356 void
358  const std::size_t vertexIndex
359 ) {
360  assert(vertexIndex < numberOfVertices());
361 
362  // erase all edges connected to the vertex
363  while(vertices_[vertexIndex].size() != 0) {
364  eraseEdge(vertices_[vertexIndex].begin()->edge());
365  }
366 
367  if(vertexIndex == numberOfVertices()-1) { // if the last vertex is to be erased
368  vertices_.pop_back(); // erase vertex
369  visitor_.eraseVertex(vertexIndex);
370  }
371  else { // if a vertex is to be erased which is not the last vertex
372  // move last vertex to the free position:
373 
374  // collect indices of edges affected by the move
375  std::size_t movingVertexIndex = numberOfVertices() - 1;
376  std::set<std::size_t> affectedEdgeIndices;
377  for(Vertex::const_iterator it = vertices_[movingVertexIndex].begin();
378  it != vertices_[movingVertexIndex].end(); ++it) {
379  affectedEdgeIndices.insert(it->edge());
380  }
381 
382  // for all affected edges:
383  for(std::set<std::size_t>::const_iterator it = affectedEdgeIndices.begin();
384  it != affectedEdgeIndices.end(); ++it) {
385  // remove adjacencies
386  eraseAdjacenciesForEdge(*it);
387 
388  // adapt vertex labels
389  for(std::size_t j=0; j<2; ++j) {
390  if(edges_[*it][j] == movingVertexIndex) {
391  edges_[*it][j] = vertexIndex;
392  }
393  }
394  // if(!(edges_[*it].directedness()) && edges_[*it][0] > edges_[*it][1]) {
395  if(edges_[*it][0] > edges_[*it][1]) {
396  std::swap(edges_[*it][0], edges_[*it][1]);
397  }
398  }
399 
400  // move vertex
401  vertices_[vertexIndex] = vertices_[movingVertexIndex]; // copy
402  vertices_.pop_back(); // erase
403 
404  // insert adjacencies for edges of moved vertex
405  for(std::set<std::size_t>::const_iterator it = affectedEdgeIndices.begin();
406  it != affectedEdgeIndices.end(); ++it) {
407  insertAdjacenciesForEdge(*it);
408  }
409 
410  visitor_.eraseVertex(vertexIndex);
411  visitor_.relabelVertex(movingVertexIndex, vertexIndex);
412  }
413 }
414 
419 template<typename VISITOR>
420 inline void
422  const std::size_t edgeIndex
423 ) {
424  assert(edgeIndex < numberOfEdges());
425 
426  eraseAdjacenciesForEdge(edgeIndex);
427  if(edgeIndex == numberOfEdges() - 1) { // if the last edge is erased
428  edges_.pop_back(); // delete
429  visitor_.eraseEdge(edgeIndex);
430  }
431  else {
432  std::size_t movingEdgeIndex = numberOfEdges() - 1;
433  eraseAdjacenciesForEdge(movingEdgeIndex);
434  edges_[edgeIndex] = edges_[movingEdgeIndex]; // copy
435  edges_.pop_back(); // delete
436  insertAdjacenciesForEdge(edgeIndex);
437  visitor_.eraseEdge(edgeIndex);
438  visitor_.relabelEdge(movingEdgeIndex, edgeIndex);
439  }
440 }
441 
449 template<typename VISITOR>
450 inline typename Graph<VISITOR>::VertexIterator
452  const std::size_t vertex
453 ) const {
454  return vertices_[vertex].begin();
455 }
456 
464 template<typename VISITOR>
465 inline typename Graph<VISITOR>::VertexIterator
467  const std::size_t vertex
468 ) const {
469  return vertices_[vertex].end();
470 }
471 
479 template<typename VISITOR>
480 inline typename Graph<VISITOR>::VertexIterator
482  const std::size_t vertex
483 ) const {
484  return vertices_[vertex].begin();
485 }
486 
494 template<typename VISITOR>
495 inline typename Graph<VISITOR>::VertexIterator
497  const std::size_t vertex
498 ) const {
499  return vertices_[vertex].end();
500 }
501 
509 template<typename VISITOR>
510 inline typename Graph<VISITOR>::EdgeIterator
512  const std::size_t vertex
513 ) const {
514  return vertices_[vertex].begin();
515 }
516 
524 template<typename VISITOR>
525 inline typename Graph<VISITOR>::EdgeIterator
527  const std::size_t vertex
528 ) const {
529  return vertices_[vertex].end();
530 }
531 
539 template<typename VISITOR>
540 inline typename Graph<VISITOR>::EdgeIterator
542  const std::size_t vertex
543 ) const {
544  return vertices_[vertex].begin();
545 }
546 
554 template<typename VISITOR>
555 inline typename Graph<VISITOR>::EdgeIterator
557  const std::size_t vertex
558 ) const {
559  return vertices_[vertex].end();
560 }
561 
569 template<typename VISITOR>
570 inline typename Graph<VISITOR>::AdjacencyIterator
572  const std::size_t vertex
573 ) const {
574  return vertices_[vertex].begin();
575 }
576 
584 template<typename VISITOR>
585 inline typename Graph<VISITOR>::AdjacencyIterator
587  const std::size_t vertex
588 ) const {
589  return vertices_[vertex].end();
590 }
591 
599 template<typename VISITOR>
600 inline typename Graph<VISITOR>::AdjacencyIterator
602  const std::size_t vertex
603 ) const {
604  return vertices_[vertex].begin();
605 }
606 
614 template<typename VISITOR>
615 inline typename Graph<VISITOR>::AdjacencyIterator
617  const std::size_t vertex
618 ) const {
619  return vertices_[vertex].end();
620 }
621 
626 template<typename VISITOR>
627 inline void
629  const std::size_t number
630 ) {
631  vertices_.reserve(number);
632 }
633 
638 template<typename VISITOR>
639 inline void
641  const std::size_t number
642 ) {
643  edges_.reserve(number);
644 }
645 
651 template<typename VISITOR>
652 inline const typename Graph<VISITOR>::AdjacencyType&
654  const std::size_t vertex,
655  const std::size_t j
656 ) const {
657  return vertices_[vertex][j];
658 }
659 
665 template<typename VISITOR>
666 inline const typename Graph<VISITOR>::AdjacencyType&
668  const std::size_t vertex,
669  const std::size_t j
670 ) const {
671  return vertices_[vertex][j];
672 }
673 
682 template<typename VISITOR>
683 inline std::pair<bool, std::size_t>
685  const std::size_t vertex0,
686  const std::size_t vertex1
687 ) const {
688  assert(vertex0 < numberOfVertices());
689  assert(vertex1 < numberOfVertices());
690 
691  std::size_t v0 = vertex0;
692  std::size_t v1 = vertex1;
693  if(numberOfEdgesFromVertex(vertex1) < numberOfEdgesFromVertex(vertex0)) {
694  v0 = vertex1;
695  v1 = vertex0;
696  }
697  VertexIterator it = std::lower_bound(
698  verticesFromVertexBegin(v0),
699  verticesFromVertexEnd(v0),
700  v1
701  ); // binary search
702  if(it != verticesFromVertexEnd(v0) && *it == v1) {
703  // access the corresponding edge in constant time
704  const std::size_t j = std::distance(verticesFromVertexBegin(v0), it);
705  return std::make_pair(true, edgeFromVertex(v0, j));
706  }
707  else {
708  return std::make_pair(false, 0);
709  }
710 }
711 
716 template<typename VISITOR>
717 inline bool
719  return multipleEdgesEnabled_;
720 }
721 
728 template<typename VISITOR>
729 inline bool&
731  return multipleEdgesEnabled_;
732 }
733 
734 template<typename VISITOR>
735 inline void
737  const std::size_t edgeIndex
738 ) {
739  const Edge& edge = edges_[edgeIndex];
740  const std::size_t vertexIndex0 = edge[0];
741  const std::size_t vertexIndex1 = edge[1];
742  vertices_[vertexIndex0].insert(
743  AdjacencyType(vertexIndex1, edgeIndex)
744  );
745  if(vertexIndex1 != vertexIndex0) {
746  vertices_[vertexIndex1].insert(
747  AdjacencyType(vertexIndex0, edgeIndex)
748  );
749  }
750 }
751 
752 template<typename VISITOR>
753 inline void
754 Graph<VISITOR>::eraseAdjacenciesForEdge(
755  const std::size_t edgeIndex
756 ) {
757  const Edge& edge = edges_[edgeIndex];
758  const std::size_t vertexIndex0 = edge[0];
759  const std::size_t vertexIndex1 = edge[1];
760  Vertex& vertex0 = vertices_[vertexIndex0];
761  Vertex& vertex1 = vertices_[vertexIndex1];
762 
763  AdjacencyType adj(vertexIndex1, edgeIndex);
764  RandomAccessSet<AdjacencyType>::iterator it = vertex0.find(adj);
765  assert(it != vertex0.end());
766  vertex0.erase(it);
767 
768  if(vertexIndex1 != vertexIndex0) { // if not a self-edge
769  adj.vertex() = vertexIndex0;
770  it = vertex1.find(adj);
771  assert(it != vertex1.end());
772  vertex1.erase(it);
773  }
774 }
775 
776 } // namespace graph
777 } // namespace andres
778 
779 #endif // #ifndef ANDRES_GRAPH_HXX