CMR  1.3.0
find_wheel_minor.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include "matrix.hpp"
4 #include "matrix_permuted.hpp"
5 #include "matrix_reorder.hpp"
6 #include "matroid.hpp"
7 #include "matroid_permuted.hpp"
8 #include "matroid_reorder.hpp"
9 #include "separation.hpp"
10 #include "matrix_modified.hpp"
11 #include "bipartite_graph_bfs.hpp"
12 #include "comparators.hpp"
13 
14 namespace tu
15 {
16 
22  {
23  typedef int value_type;
24 
32  zero_block_matrix_modifier(size_t height, size_t width) :
33  height_(height), width_(width)
34  {
35 
36  }
37 
47  int operator ()(size_t i, size_t j, int value)
48  {
49  if (i < height_ && j < width_)
50  return 0;
51  else
52  return value;
53  }
54 
55  private:
56  size_t height_;
57  size_t width_;
58  };
59 
70  template <typename MatroidType, typename MatrixType>
72  matroid_element_set& extra_elements)
73  {
74  assert (permuted_matrix.size1() >= 3 && permuted_matroid.size2() >= 3);
75 
77  matroid_reorder_columns(permuted_matroid, permuted_matrix, 0, 1, 0, permuted_matroid.size2(), std::greater <int>());
78  size_t count_first_row_ones = matrix_count_property_column_series(permuted_matrix, 0, 1, 0, permuted_matrix.size2(), is_non_zero());
79 
81  if (count_first_row_ones == 0)
82  {
83  return separation(std::make_pair(1, 0));
84  }
85 
86  matroid_reorder_rows(permuted_matroid, permuted_matrix, 1, permuted_matroid.size1(), 0, 1, std::greater <int>());
87  size_t count_first_column_ones = matrix_count_property_row_series(permuted_matrix, 0, permuted_matroid.size1(), 0, 1, is_non_zero());
88 
90  if (count_first_row_ones == 1)
91  {
92  if (count_first_column_ones == 0)
93  {
94  return separation(std::make_pair(1, 1));
95  }
96  else
97  {
98  return separation(std::make_pair(1, 1), std::make_pair(1, 0));
99  }
100  }
101  else if (count_first_column_ones == 1)
102  {
103  return separation(std::make_pair(1, 1), std::make_pair(0, 1));
104  }
105 
106  assert ((permuted_matrix(0,0) == 1) && (permuted_matrix(1,0) == 1) && (permuted_matrix(0,1) == 1));
107 
109  if (permuted_matrix(1, 1) != 1)
110  {
111  matroid_binary_pivot(permuted_matroid, permuted_matrix, 0, 0);
112  extra_elements.insert(permuted_matroid.name1(0));
113  extra_elements.insert(permuted_matroid.name2(0));
114  }
115 
116  assert ((permuted_matrix(0,0) == 1) && (permuted_matrix(1,0) == 1) && (permuted_matrix(0,1) == 1) && (permuted_matrix(1,1) == 1));
117 
119  matroid_reorder_columns(permuted_matroid, permuted_matrix, 0, 2, 2, permuted_matroid.size2(), std::greater <int>());
120  size_t block_width = 2 + matrix_count_property_column_series(permuted_matrix, 0, 2, 2, permuted_matrix.size2(), is_all_ones());
121 
122  matroid_reorder_rows(permuted_matroid, permuted_matrix, 2, permuted_matroid.size1(), 0, block_width, std::greater <int>());
123 
124  size_t block_height = 2 + matrix_count_property_row_series(permuted_matrix, 2, permuted_matrix.size1(), 0, block_width, is_all_ones());
125 
127  zero_block_matrix_modifier modifier(block_height, block_width);
128  matrix_modified <matrix_permuted <MatrixType> , zero_block_matrix_modifier> modified_matrix(permuted_matrix, modifier);
129  bipartite_graph_dimensions dim(permuted_matrix.size1(), permuted_matrix.size2());
130  std::vector <bipartite_graph_dimensions::index_type> start_nodes(block_height);
131  for (size_t i = 0; i < block_height; i++)
132  start_nodes[i] = dim.row_to_index(i);
133  std::vector <bipartite_graph_dimensions::index_type> end_nodes(block_width);
134  for (size_t i = 0; i < block_width; i++)
135  end_nodes[i] = dim.column_to_index(i);
136 
137  std::vector <bipartite_graph_bfs_node> bfs_result;
138  bool found_path = bipartite_graph_bfs(modified_matrix, dim, start_nodes, end_nodes, false, bfs_result);
139 
141  if (!found_path)
142  {
143  std::pair <size_t, size_t> split(0, 0);
144 
146  std::vector <int> reachable(permuted_matrix.size1());
147  for (size_t i = 0; i < permuted_matrix.size1(); ++i)
148  {
149  const bipartite_graph_bfs_node& node = bfs_result[dim.row_to_index(i)];
150  int value = (node.is_reachable() ? (node.distance > 0 ? 2 : 1) : 0);
151  reachable[permuted_matrix.perm1()(i)] = value;
152  if (value == 0)
153  split.first++;
154  }
155  vector_less <int, std::less <int> > less(reachable, std::less <int>());
156 
157  sort(permuted_matrix.perm1(), less);
158  permuted_matroid.perm1() = permuted_matrix.perm1();
159 
161  reachable.resize(permuted_matrix.size2());
162  for (size_t i = 0; i < permuted_matrix.size2(); ++i)
163  {
164  const bipartite_graph_bfs_node& node = bfs_result[dim.column_to_index(i)];
165  int value = (node.is_reachable() ? 2 : (node.distance == -2 ? 1 : 0));
166  reachable[permuted_matrix.perm2()(i)] = value;
167  if (value < 2)
168  split.second++;
169  }
170 
171  sort(permuted_matrix.perm2(), less);
172  permuted_matroid.perm2() = permuted_matrix.perm2();
173 
174  return separation(split, std::make_pair(split.first, split.second - 1));
175  }
176 
179  for (std::vector <bipartite_graph_dimensions::index_type>::const_iterator iter = end_nodes.begin(); iter != end_nodes.end(); ++iter)
180  {
181  if (bfs_result[*iter].is_reachable())
182  nearest_end = *iter;
183  }
184 
185  assert (bfs_result[nearest_end].is_reachable());
186 
187  size_t w3_one_column = dim.index_to_column(nearest_end);
188  size_t nearest_distance = bfs_result[nearest_end].distance + 1;
189 
190  assert (nearest_distance % 2 == 0);
191 
192  size_t last_index = nearest_end;
193  size_t current_index = bfs_result[last_index].predecessor;
194 
196  size_t w3_one_row = 0;
197  size_t w3_path_column = 0;
198  size_t w3_path_row = dim.index_to_row(current_index);
199  size_t w3_zero_column = 0;
200  while (permuted_matrix(w3_path_row, w3_zero_column) != 0)
201  {
202  w3_zero_column++;
203  assert (w3_zero_column < block_width);
204  }
205 
207  while (last_index != current_index)
208  {
209  std::pair <size_t, size_t> coords = dim.indexes_to_coordinates(current_index, last_index);
210 
211  if ((bfs_result[current_index].distance % 2 == 0) && (bfs_result[current_index].distance >= 2) && (bfs_result[current_index].distance + 2
212  < (int) nearest_distance))
213  {
214  matroid_binary_pivot(permuted_matroid, permuted_matrix, coords.first, coords.second);
215  extra_elements.insert(permuted_matroid.name1(coords.first));
216  extra_elements.insert(permuted_matroid.name2(coords.second));
217  }
218 
219  if (bfs_result[current_index].distance == 1)
220  {
221  assert (dim.is_column(current_index));
222 
223  w3_path_column = dim.index_to_column(current_index);
224  }
225  else if (bfs_result[current_index].distance == 0)
226  {
227  assert (dim.is_row(current_index));
228 
229  w3_one_row = dim.index_to_row(current_index);
230  }
231 
232  last_index = current_index;
233  current_index = bfs_result[current_index].predecessor;
234  }
235 
237  size_t w3_zero_row = 0;
238  while (permuted_matrix(w3_zero_row, w3_path_column) != 0)
239  {
240  w3_zero_row++;
241  assert (w3_zero_row< block_height);
242  }
243 
244  assert (permuted_matrix (w3_one_row, w3_one_column) == 1);
245  assert (permuted_matrix (w3_one_row, w3_zero_column) == 1);
246  assert (permuted_matrix (w3_one_row, w3_path_column) == 1);
247  assert (permuted_matrix (w3_zero_row, w3_one_column) == 1);
248  assert (permuted_matrix (w3_zero_row, w3_zero_column) == 1);
249  assert (permuted_matrix (w3_zero_row, w3_path_column) == 0);
250  assert (permuted_matrix (w3_path_row, w3_one_column) == 1);
251  assert (permuted_matrix (w3_path_row, w3_zero_column) == 0);
252  assert (permuted_matrix (w3_path_row, w3_path_column) == 1);
253 
255  if (w3_zero_row > w3_one_row)
256  {
257  matroid_permute1(permuted_matroid, permuted_matrix, w3_one_row, w3_zero_row);
258  std::swap(w3_one_row, w3_zero_row);
259  }
260  if (w3_one_row > w3_path_row)
261  {
262  matroid_permute1(permuted_matroid, permuted_matrix, w3_path_row, w3_one_row);
263  std::swap(w3_path_row, w3_one_row);
264  }
265 
266  if (w3_zero_column > w3_one_column)
267  {
268  matroid_permute2(permuted_matroid, permuted_matrix, w3_one_column, w3_zero_column);
269  std::swap(w3_one_column, w3_zero_column);
270  }
271  if (w3_one_column > w3_path_column)
272  {
273  matroid_permute2(permuted_matroid, permuted_matrix, w3_path_column, w3_one_column);
274  std::swap(w3_path_column, w3_one_column);
275  }
276 
277  matroid_permute1(permuted_matroid, permuted_matrix, 0, w3_zero_row);
278  matroid_permute1(permuted_matroid, permuted_matrix, 1, w3_one_row);
279  matroid_permute1(permuted_matroid, permuted_matrix, 2, w3_path_row);
280 
281  matroid_permute2(permuted_matroid, permuted_matrix, 0, w3_zero_column);
282  matroid_permute2(permuted_matroid, permuted_matrix, 1, w3_one_column);
283  matroid_permute2(permuted_matroid, permuted_matrix, 2, w3_path_column);
284 
285  return separation();
286  }
287 
288 } /* namespace tu */
Definition: matrix_modified.hpp:14
Definition: matrix_permuted.hpp:17
const permutation_type & perm2() const
Definition: matrix_permuted.hpp:92
const permutation_type & perm1() const
Definition: matrix_permuted.hpp:74
size_type size2() const
Definition: matrix_permuted.hpp:65
size_type size1() const
Definition: matrix_permuted.hpp:56
Definition: matroid_permuted.hpp:14
size_type size1() const
Definition: matroid_permuted.hpp:41
const permutation_type & perm2() const
Definition: matroid_permuted.hpp:77
const permutation_type & perm1() const
Definition: matroid_permuted.hpp:59
reference_type name1(size_type index)
Definition: matroid_permuted.hpp:96
size_type size2() const
Definition: matroid_permuted.hpp:50
reference_type name2(size_type index)
Definition: matroid_permuted.hpp:116
void resize(size_type new_size)
Definition: permutations.hpp:280
Definition: separation.hpp:18
Definition: algorithm.hpp:14
void sort(permutation &permutation, size_t first, size_t beyond, Less &less)
Definition: permutations.hpp:583
void matroid_reorder_columns(MatroidType &matroid, MatrixType &matrix, size_t row_first, size_t row_beyond, size_t column_first, size_t column_beyond, ElementLess element_less)
Definition: matroid_reorder.hpp:81
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
void matroid_permute1(matroid< NameType > &matroid, size_t index1, size_t index2)
Definition: matroid.hpp:162
void matroid_reorder_rows(MatroidType &matroid, MatrixType &matrix, size_t row_first, size_t row_beyond, size_t column_first, size_t column_beyond, ElementLess element_less)
Definition: matroid_reorder.hpp:60
void matroid_permute2(matroid< NameType > &matroid, size_t index1, size_t index2)
Definition: matroid.hpp:192
separation find_wheel_minor(matroid_permuted< MatroidType > &permuted_matroid, matrix_permuted< MatrixType > &permuted_matrix, matroid_element_set &extra_elements)
Definition: find_wheel_minor.hpp:71
void matroid_binary_pivot(matroid< NameType > &matroid, size_t i, size_t j)
Definition: matroid.hpp:222
std::set< int > matroid_element_set
Definition: matroid_decomposition.hpp:19
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
Definition: bipartite_graph_bfs.hpp:39
bool is_row(index_type index) const
Definition: bipartite_graph_bfs.hpp:88
std::pair< size_t, size_t > indexes_to_coordinates(index_type first, index_type second) const
Definition: bipartite_graph_bfs.hpp:155
size_t index_to_column(index_type index) const
Definition: bipartite_graph_bfs.hpp:119
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 index_type
Definition: bipartite_graph_bfs.hpp:40
bool is_column(index_type index) const
Definition: bipartite_graph_bfs.hpp:98
Definition: comparators.hpp:60
Definition: comparators.hpp:13
Definition: comparators.hpp:108
Definition: find_wheel_minor.hpp:22
zero_block_matrix_modifier(size_t height, size_t width)
Definition: find_wheel_minor.hpp:32
int operator()(size_t i, size_t j, int value)
Definition: find_wheel_minor.hpp:47
int value_type
Definition: find_wheel_minor.hpp:23