andres::graph
bfs.hxx
1 #pragma once
2 #ifndef ANDRES_GRAPH_BFS_HXX
3 #define ANDRES_GRAPH_BFS_HXX
4 
5 #include <cassert>
6 #include <cstddef>
7 #include <limits>
8 #include <queue>
9 #include <type_traits>
10 #include <vector>
11 
12 #include "subgraph.hxx"
13 
14 namespace andres {
15 namespace graph {
16 
17 template<typename S = std::size_t>
19 public:
20  typedef S size_type;
21 
22  static const size_type NOT_VISITED;
23 
25  : depth_(size, NOT_VISITED)
26  {}
27  template<typename GRAPH>
28  BreadthFirstSearchData(const GRAPH& graph)
29  : depth_(graph.numberOfVertices(), NOT_VISITED)
30  {}
32  { depth_[v] = depth; queue_.push(v); }
33  void clearQueue()
34  { queue_ = std::queue<size_type>(); }
35  bool empty() const
36  { return queue_.empty(); }
38  { std::fill(depth_.begin(), depth_.end(), NOT_VISITED); }
40  { const size_type v = queue_.front(); queue_.pop(); return v; }
41  size_type depth(const size_type v) const
42  { return depth_[v]; }
44  { return depth_[v]; }
45 
46 private:
47  std::vector<size_type> depth_;
48  std::queue<size_type> queue_;
49 };
50 template<typename S>
51  const S BreadthFirstSearchData<S>::NOT_VISITED = std::numeric_limits<S>::max();
52 
53 template<typename GRAPH, typename CALLBACK>
54 inline void
56  const GRAPH& g,
57  const std::size_t start_vertex,
58  CALLBACK& callback
59 )
60 {
62  breadthFirstSearch(g, DefaultSubgraphMask<>(), start_vertex, callback, data);
63 }
64 
65 template<typename GRAPH, typename CALLBACK, typename = typename std::enable_if<!std::is_lvalue_reference<CALLBACK>::value>::type>
66 inline void
68  const GRAPH& g,
69  const std::size_t start_vertex,
70  CALLBACK&& callback
71 )
72 {
74  breadthFirstSearch(g, DefaultSubgraphMask<>(), start_vertex, callback, data);
75 }
76 
77 template<typename GRAPH, typename CALLBACK>
78 inline void
80  const GRAPH& g,
81  const std::size_t start_vertex,
82  CALLBACK& callback,
84 )
85 {
86  breadthFirstSearch(g, DefaultSubgraphMask<>(), start_vertex, callback, data);
87 }
88 
89 template<typename GRAPH, typename CALLBACK, typename = typename std::enable_if<!std::is_lvalue_reference<CALLBACK>::value>::type>
90 inline void
92  const GRAPH& g,
93  const std::size_t start_vertex,
94  CALLBACK&& callback,
96 )
97 {
98  breadthFirstSearch(g, DefaultSubgraphMask<>(), start_vertex, callback, data);
99 }
100 
101 template<typename GRAPH, typename SUBGRAPH, typename CALLBACK>
102 inline void
104  const GRAPH& g,
105  const SUBGRAPH& subgraph_mask,
106  const std::size_t start_vertex,
107  CALLBACK& callback
108 )
109 {
111  breadthFirstSearch(g, subgraph_mask, start_vertex, callback, data);
112 }
113 
114 template<typename GRAPH, typename SUBGRAPH, typename CALLBACK, typename = typename std::enable_if<!std::is_lvalue_reference<CALLBACK>::value>::type>
115 inline void
117  const GRAPH& g,
118  const SUBGRAPH& subgraph_mask,
119  const std::size_t start_vertex,
120  CALLBACK&& callback
121 )
122 {
124  breadthFirstSearch(g, subgraph_mask, start_vertex, callback, data);
125 }
126 
127 template<typename GRAPH, typename SUBGRAPH, typename CALLBACK>
128 inline void
130  const GRAPH& g,
131  const SUBGRAPH& subgraph_mask,
132  const std::size_t start_vertex,
133  CALLBACK& callback,
135 )
136 {
137  assert(start_vertex < g.numberOfVertices());
138 
139  {
140  bool proceed;
141  bool add;
142  callback(start_vertex, 0, proceed, add);
143  if(!proceed) {
144  return;
145  }
146  if(add) {
147  data.add(start_vertex, 0);
148  }
149  }
150  while(!data.empty()) {
151  const auto v = data.next();
152  const auto depth = data.depth(v) + 1;
153 
154  auto e_it = g.edgesFromVertexBegin(v);
155  for(auto it = g.verticesFromVertexBegin(v); it != g.verticesFromVertexEnd(v); ++it, ++e_it)
157  subgraph_mask.vertex(*it) &&
158  subgraph_mask.edge(*e_it))
159  {
160  bool proceed;
161  bool add;
162 
163  callback(*it, depth, proceed, add);
164 
165  if(!proceed)
166  {
167  data.clearQueue();
168  return;
169  }
170 
171  if(add)
172  data.add(*it, depth);
173  }
174  }
175 }
176 
177 template<typename GRAPH, typename SUBGRAPH, typename CALLBACK, typename = typename std::enable_if<!std::is_lvalue_reference<CALLBACK>::value>::type>
178 inline void
180  const GRAPH& g,
181  const SUBGRAPH& subgraph_mask,
182  const std::size_t start_vertex,
183  CALLBACK&& callback,
185 )
186 {
187  breadthFirstSearch(g, subgraph_mask, start_vertex, callback, data);
188 }
189 
190 } // namespace graph
191 } // namespace andres
192 
193 #endif