andres::graph
components.hxx
1 #pragma once
2 #ifndef ANDRES_GRAPH_COMPONENTS_HXX
3 #define ANDRES_GRAPH_COMPONENTS_HXX
4 
5 #include <cstddef>
6 #include <vector>
7 #include <queue>
8 #include <algorithm> // std::fill
9 
10 #include "andres/partition.hxx"
11 
12 #include "subgraph.hxx"
13 
14 namespace andres {
15 namespace graph {
16 
18 template<class GRAPH>
20  typedef GRAPH Graph;
21 
23  std::size_t build(const Graph&);
24  template<class SUBGRAPH_MASK>
25  std::size_t build(const Graph&, const SUBGRAPH_MASK&);
26  bool areConnected(const std::size_t, const std::size_t) const;
27 
28  std::vector<std::size_t> labels_;
29 };
30 
32 template<class GRAPH>
34  typedef GRAPH Graph;
35 
37  std::size_t build(const Graph&);
38  template<class SUBGRAPH_MASK>
39  std::size_t build(const Graph&, const SUBGRAPH_MASK&);
40  bool areConnected(const std::size_t, const std::size_t) const;
41 
42  andres::Partition<std::size_t> partition_;
43 };
44 
52 template<class GRAPH, class ITERATOR>
53 inline std::size_t
55  const GRAPH& graph,
56  ITERATOR labeling
57 ) {
58  return labelComponents(graph, DefaultSubgraphMask<>(), labeling);
59 }
60 
69 template<class GRAPH, class SUBGRAPH_MASK, class ITERATOR>
70 std::size_t
72  const GRAPH& graph,
73  const SUBGRAPH_MASK& mask,
74  ITERATOR labeling
75 ) {
76  std::size_t label = 0;
77  std::vector<bool> visited(graph.numberOfVertices(), false);
78  std::queue<std::size_t> queue;
79  for(std::size_t v = 0; v < graph.numberOfVertices(); ++v) {
80  if(mask.vertex(v)) {
81  if(!visited[v]) {
82  labeling[v] = label; // label
83  queue.push(v);
84  visited[v] = true;
85  while(!queue.empty()) {
86  std::size_t w = queue.front();
87  queue.pop();
88  for(typename GRAPH::AdjacencyIterator it = graph.adjacenciesFromVertexBegin(w);
89  it != graph.adjacenciesFromVertexEnd(w); ++it) {
90  if(mask.edge(it->edge())
91  && mask.vertex(it->vertex())
92  && !visited[it->vertex()]) {
93  labeling[it->vertex()] = label; // label
94  queue.push(it->vertex());
95  visited[it->vertex()] = true;
96  }
97  }
98  }
99  label++;
100  }
101  }
102  else {
103  labeling[v] = 0;
104  }
105  }
106  return label;
107 }
108 
109 template<class GRAPH>
110 inline
112 : labels_()
113 {}
114 
115 template<class GRAPH>
116 inline std::size_t
118  const Graph& graph
119 ) {
120  return build(graph, DefaultSubgraphMask<>());
121 }
122 
123 template<class GRAPH>
124 template<class SUBGRAPH_MASK>
125 inline std::size_t
127  const Graph& graph,
128  const SUBGRAPH_MASK& mask
129 ) {
130  labels_.resize(graph.numberOfVertices());
131  return labelComponents(graph, mask, labels_.begin());
132 }
133 
134 template<class GRAPH>
135 inline bool
137  const std::size_t vertex0,
138  const std::size_t vertex1
139 ) const {
140  return labels_[vertex0] == labels_[vertex1];
141 }
142 
143 template<class GRAPH>
144 inline
146 : partition_()
147 {}
148 
149 template<class GRAPH>
150 inline std::size_t
152  const Graph& graph
153 ) {
154  return build(graph, DefaultSubgraphMask<>());
155 }
156 
157 template<class GRAPH>
158 template<class SUBGRAPH_MASK>
159 inline std::size_t
161  const Graph& graph,
162  const SUBGRAPH_MASK& mask
163 ) {
164  partition_.assign(graph.numberOfVertices());
165  for(std::size_t edge = 0; edge < graph.numberOfEdges(); ++edge) {
166  if(mask.edge(edge)) {
167  const std::size_t v0 = graph.vertexOfEdge(edge, 0);
168  const std::size_t v1 = graph.vertexOfEdge(edge, 1);
169  if(mask.vertex(v0) && mask.vertex(v1)) {
170  partition_.merge(v0, v1);
171  }
172  }
173  }
174  return partition_.numberOfSets();
175 }
176 
177 template<class GRAPH>
178 inline bool
180  const std::size_t vertex0,
181  const std::size_t vertex1
182 ) const {
183  return partition_.find(vertex0) == partition_.find(vertex1);
184 }
185 
186 } // namespace graph
187 } // namespace andres
188 
189 #endif // #ifndef ANDRES_GRAPH_COMPONENTS_HXX