CMR  1.3.0
bipartite_graph_bfs.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <vector>
4 #include <list>
5 
6 namespace tu
7 {
8 
15  {
17  int distance;
18 
20  size_t predecessor;
21 
26  inline bool is_reachable() const
27  {
28  return distance >= 0;
29  }
30  };
31 
39  {
40  typedef size_t index_type;
41 
51  _height(height), _width(width)
52  {
53 
54  }
55 
60  inline size_t height() const
61  {
62  return _height;
63  }
64 
69  inline size_t width() const
70  {
71  return _width;
72  }
73 
78  inline size_t size() const
79  {
80  return _width + _height;
81  }
82 
88  inline bool is_row(index_type index) const
89  {
90  return index < _height;
91  }
92 
98  inline bool is_column(index_type index) const
99  {
100  return index >= _height;
101  }
102 
108  inline size_t index_to_row(index_type index) const
109  {
110  assert(is_row(index));
111  return index;
112  }
113 
119  inline size_t index_to_column(index_type index) const
120  {
121  assert(is_column(index));
122  return index - _height;
123  }
124 
130  inline index_type row_to_index(size_t row) const
131  {
132  return row;
133  }
134 
140  inline index_type column_to_index(size_t column) const
141  {
142  return column + _height;
143  }
144 
155  inline std::pair <size_t, size_t> indexes_to_coordinates(index_type first, index_type second) const
156  {
157  if (first < _height)
158  return std::make_pair(first, second - _height);
159  else
160  return std::make_pair(second, first - _height);
161  }
162 
163  private:
164  size_t _height;
165  size_t _width;
166  };
167 
181  template <typename MatrixType, typename StartNodesContainerType, typename EndNodesContainerType>
182  inline bool bipartite_graph_bfs(const MatrixType& matrix, const bipartite_graph_dimensions& dimensions, const StartNodesContainerType& start_nodes,
183  const EndNodesContainerType& end_nodes, bool reach_all, std::vector <bipartite_graph_bfs_node>& result)
184  {
185  typedef std::vector <bipartite_graph_bfs_node> node_vector_type;
186  typedef std::list <size_t> node_list_type;
187 
188  const size_t size = dimensions.size();
189  const size_t height = dimensions.height();
190 
191  assert(height <= matrix.size1());
192  assert(dimensions.width() <= matrix.size2());
193 
195  int needed_end_nodes = (reach_all ? end_nodes.size() : 1);
196  node_list_type unprocessed;
197  result.resize(size);
198  for (typename node_vector_type::iterator iter = result.begin(); iter != result.end(); ++iter)
199  {
200  iter->distance = -1;
201  iter->predecessor = 0;
202  }
203  for (typename StartNodesContainerType::const_iterator iter = start_nodes.begin(); iter != start_nodes.end(); ++iter)
204  {
205  result[*iter].distance = 0;
206  result[*iter].predecessor = *iter;
207  unprocessed.push_back(*iter);
208  }
209  for (typename EndNodesContainerType::const_iterator iter = end_nodes.begin(); iter != end_nodes.end(); ++iter)
210  {
211  if (result[*iter].distance == 0)
212  --needed_end_nodes;
213  result[*iter].distance = -2;
214  }
215 
216  if (needed_end_nodes <= 0)
217  return true;
218 
220  while (!unprocessed.empty())
221  {
222  size_t current_index = unprocessed.front();
223  int current_distance = result[current_index].distance;
224  unprocessed.pop_front();
225 
226  if (dimensions.is_row(current_index))
227  {
229  const size_t row = current_index;
230  for (size_t neighbor_index = height; neighbor_index < size; ++neighbor_index)
231  {
232  const size_t column = neighbor_index - height;
233  if (!result[neighbor_index].is_reachable() && matrix(row, column))
234  {
235  if (result[neighbor_index].distance == -2)
236  --needed_end_nodes;
237 
238  result[neighbor_index].distance = current_distance + 1;
239  result[neighbor_index].predecessor = current_index;
240 
241  if (needed_end_nodes <= 0)
242  return true;
243 
244  unprocessed.push_back(neighbor_index);
245  }
246  }
247  }
248  else
249  {
250  assert(dimensions.is_column(current_index));
251 
253  const size_t column = current_index - height;
254  for (size_t neighbor_index = 0; neighbor_index < height; ++neighbor_index)
255  {
256  const size_t row = neighbor_index;
257  if (!result[neighbor_index].is_reachable() && matrix(row, column))
258  {
259  if (result[neighbor_index].distance == -2)
260  --needed_end_nodes;
261 
262  result[neighbor_index].distance = current_distance + 1;
263  result[neighbor_index].predecessor = current_index;
264 
265  if (needed_end_nodes <= 0)
266  return true;
267 
268  unprocessed.push_back(neighbor_index);
269  }
270  }
271  }
272  }
273  return false;
274  }
275 
276 } /* namespace tu */
Definition: algorithm.hpp:14
bool bipartite_graph_bfs(const MatrixType &matrix, const bipartite_graph_dimensions &dimensions, const StartNodesContainerType &start_nodes, const EndNodesContainerType &end_nodes, bool reach_all, std::vector< bipartite_graph_bfs_node > &result)
Definition: bipartite_graph_bfs.hpp:182
Definition: bipartite_graph_bfs.hpp:15
bool is_reachable() const
Definition: bipartite_graph_bfs.hpp:26
int distance
Combinatorial distance to the search root or -1 if not reachable.
Definition: bipartite_graph_bfs.hpp:17
size_t predecessor
Index of the predecessor in the search tree.
Definition: bipartite_graph_bfs.hpp:20
Definition: bipartite_graph_bfs.hpp:39
bool is_row(index_type index) const
Definition: bipartite_graph_bfs.hpp:88
size_t width() const
Definition: bipartite_graph_bfs.hpp:69
std::pair< size_t, size_t > indexes_to_coordinates(index_type first, index_type second) const
Definition: bipartite_graph_bfs.hpp:155
size_t size() const
Definition: bipartite_graph_bfs.hpp:78
size_t index_to_column(index_type index) const
Definition: bipartite_graph_bfs.hpp:119
bipartite_graph_dimensions(size_t height, size_t width)
Definition: bipartite_graph_bfs.hpp:50
index_type column_to_index(size_t column) const
Definition: bipartite_graph_bfs.hpp:140
index_type row_to_index(size_t row) const
Definition: bipartite_graph_bfs.hpp:130
size_t index_to_row(index_type index) const
Definition: bipartite_graph_bfs.hpp:108
size_t height() const
Definition: bipartite_graph_bfs.hpp:60
size_t index_type
Definition: bipartite_graph_bfs.hpp:40
bool is_column(index_type index) const
Definition: bipartite_graph_bfs.hpp:98