CMR  1.3.0
find_minor_sequence.hpp
Go to the documentation of this file.
1 #pragma once
2 
5 #include "separation.hpp"
6 #include "matroid_transposed.hpp"
7 #include "matrix_transposed.hpp"
8 #include "matrix_modified.hpp"
10 #include "comparators.hpp"
11 #include "logger.hpp"
12 
13 namespace tu
14 {
15 
28  template <typename MatroidType, typename MatrixType, typename NestedMinorSequenceType, typename RowThreeConnectivity,
29  typename ColumnThreeConnectivity>
30  bool find_simple_row_extension(MatroidType& matroid, MatrixType& matrix, NestedMinorSequenceType& nested_minors,
31  RowThreeConnectivity& row_three_connectivity, ColumnThreeConnectivity& column_three_connectivity)
32  {
33  for (size_t row = nested_minors.height(); row < matroid.size1(); ++row)
34  {
35  if (row_three_connectivity.is_other(row))
36  {
37  matroid_permute1(matroid, matrix, nested_minors.height(), row);
38  row_three_connectivity.swap_vectors(nested_minors.height(), row);
39  nested_minors.push(nested_minor_sequence::ONE_ROW);
40  row_three_connectivity.enlarge_base();
41  column_three_connectivity.enlarge_dimension();
42  return true;
43  }
44  }
45 
46  return false;
47  }
48 
64  template <typename MatroidType, typename MatrixType, typename NestedMinorSequenceType, typename RowThreeConnectivity,
65  typename ColumnThreeConnectivity>
66  char find_parallel_or_unit_vector(MatroidType& matroid, MatrixType& matrix, NestedMinorSequenceType& nested_minors,
67  RowThreeConnectivity& row_three_connectivity, ColumnThreeConnectivity& column_three_connectivity, size_t& index)
68  {
69  CMR_UNUSED(matrix);
70 
71  bool found_column = false;
72  for (size_t row = nested_minors.height(); row < matroid.size1(); ++row)
73  {
74  if (row_three_connectivity.is_parallel(row))
75  {
76  index = row_three_connectivity.get_referred(row);
77  return 'r';
78  }
79  else if (row_three_connectivity.is_unit(row))
80  {
81  index = row_three_connectivity.get_referred(row);
82  found_column = true;
83  }
84  }
85 
86  for (size_t column = nested_minors.width(); column < matroid.size2(); ++column)
87  {
88  if (column_three_connectivity.is_unit(column))
89  {
90  index = column_three_connectivity.get_referred(column);
91  return 'r';
92  }
93  else if (column_three_connectivity.is_parallel(column))
94  {
95  index = column_three_connectivity.get_referred(column);
96  found_column = true;
97  }
98  }
99  return found_column ? 'c' : 0;
100  }
101 
109  {
110  typedef int value_type;
111  typedef unsigned char index_type;
112 
113  enum { BLOCK = 0 };
114  enum { ZERO = 1 };
115  enum { START = 2 };
116  enum { END0 = 3 };
117  enum { END1 = 4 };
118 
127  elaborate_extension_matrix_modifier(const std::vector <index_type>& row_types, const std::vector <index_type>& column_types) :
128  row_types_(row_types), column_types_(column_types)
129  {
130 
131  }
132 
142  int operator ()(size_t i, size_t j, int value)
143  {
144  switch (5 * row_types_[i] + column_types_[j])
145  {
146  case 5 * ZERO + ZERO:
147  case 5 * ZERO + START:
148  case 5 * ZERO + END0:
149  case 5 * ZERO + END1:
150  case 5 * START + ZERO:
151  case 5 * END0 + ZERO:
152  case 5 * END0 + START:
153  case 5 * END0 + END0:
154  case 5 * END0 + END1:
155  case 5 * END1 + ZERO:
156  case 5 * END1 + START:
157  case 5 * END1 + END0:
158  case 5 * END1 + END1:
159  return value;
160  case 5 * START + END0:
161  return value;
162  case 5 * START + END1:
163  return 1 - value;
164  default:
165  return 0;
166  }
167  }
168 
169  private:
170  const std::vector <index_type>& row_types_;
171  const std::vector <index_type>& column_types_;
172  };
173 
188  template <typename MatroidType, typename MatrixType, typename NestedMinorSequenceType, typename RowThreeConnectivity,
189  typename ColumnThreeConnectivity>
190  separation find_elaborate_extension(MatroidType& matroid, MatrixType& matrix, NestedMinorSequenceType& nested_minors,
191  RowThreeConnectivity& row_three_connectivity, ColumnThreeConnectivity& column_three_connectivity, size_t index,
192  matroid_element_set& extra_elements)
193  {
196  std::vector <size_t> start_nodes, end_nodes;
197  start_nodes.reserve(matroid.size1());
198  end_nodes.reserve(matroid.size1());
199 
201  std::vector <elaborate_extension_matrix_modifier::index_type> row_types(matroid.size1());
202  for (size_t row = 0; row < matroid.size1(); ++row)
203  {
204  if (row < nested_minors.height())
206  else if (row_three_connectivity.is_parallel(row) && row_three_connectivity.get_referred(row) == index)
207  {
209  start_nodes.push_back(dim.row_to_index(row));
210  }
211  else if (row_three_connectivity.is_zero(row))
213  else
214  {
216  end_nodes.push_back(dim.row_to_index(row));
217  }
218  }
219 
221  std::vector <elaborate_extension_matrix_modifier::index_type> column_types(matroid.size2());
222  for (size_t column = 0; column < matroid.size2(); ++column)
223  {
224  if (column < nested_minors.width())
225  column_types[column] = elaborate_extension_matrix_modifier::BLOCK;
226  else if (column_three_connectivity.is_unit(column) && column_three_connectivity.get_referred(column) == index)
227  {
228  column_types[column] = elaborate_extension_matrix_modifier::START;
229  start_nodes.push_back(dim.column_to_index(column));
230  }
231  else if (column_three_connectivity.is_zero(column))
232  column_types[column] = elaborate_extension_matrix_modifier::ZERO;
233  else
234  {
235  column_types[column] = matrix(index, column) == 1
238  end_nodes.push_back(dim.column_to_index(column));
239  }
240  }
241 
243  elaborate_extension_matrix_modifier modifier(row_types, column_types);
245 
246  std::vector <bipartite_graph_bfs_node> bfs_result;
247  bool found_path = bipartite_graph_bfs(modified_matrix, dim, start_nodes, end_nodes, false, bfs_result);
248 
250  if (found_path)
251  {
252  size_t nearest_end = 0;
253  for (std::vector <bipartite_graph_dimensions::index_type>::const_iterator iter = end_nodes.begin(); iter != end_nodes.end(); ++iter)
254  {
255  if (bfs_result[*iter].is_reachable())
256  nearest_end = *iter;
257  }
258  assert (bfs_result[nearest_end].is_reachable());
259 
260  size_t nearest_distance = bfs_result[nearest_end].distance;
261  size_t connecting_start = 0;
262  size_t first_connected = 0;
263  size_t last_index = nearest_end;
264  size_t current_index = bfs_result[nearest_end].predecessor;
265 
267  size_t count = 0;
268  while (last_index != current_index)
269  {
270  std::pair <size_t, size_t> coords = dim.indexes_to_coordinates(current_index, last_index);
271 
272  if ((row_types[coords.first] == elaborate_extension_matrix_modifier::ZERO) && (column_types[coords.second]
274  {
275  if (count % 2 == 0)
276  {
277  matroid_binary_pivot(matroid, matrix, coords.first, coords.second);
278  extra_elements.insert(matroid.name1(coords.first));
279  extra_elements.insert(matroid.name2(coords.second));
280  nearest_distance -= 2;
281  }
282  count++;
283  }
284 
285  if (bfs_result[current_index].distance == 0)
286  {
287  first_connected = last_index;
288  connecting_start = current_index;
289  }
290 
291  last_index = current_index;
292  current_index = bfs_result[current_index].predecessor;
293  }
294 
296  if (nearest_distance == 1)
297  {
298  if (dim.is_column(nearest_end))
299  std::swap(nearest_end, connecting_start);
300 
301  assert (dim.is_row(nearest_end));
302  assert (dim.is_column(connecting_start));
303 
304  matroid_permute1(matroid, matrix, dim.index_to_row(nearest_end), nested_minors.height());
305  matroid_permute2(matroid, matrix, dim.index_to_column(connecting_start), nested_minors.width());
306  nested_minors.push(nested_minor_sequence::ONE_ROW_ONE_COLUMN);
307  return separation();
308  }
309  else if (nearest_distance == 2)
310  {
312  if (connecting_start > nearest_end)
313  std::swap(connecting_start, nearest_end);
314 
315  if (dim.is_row(nearest_end))
316  {
317  assert (dim.is_row(connecting_start));
318 
319  matroid_permute1(matroid, matrix, dim.index_to_row(connecting_start), nested_minors.height());
320  matroid_permute1(matroid, matrix, dim.index_to_row(nearest_end), nested_minors.height() + 1);
321  matroid_permute2(matroid, matrix, nested_minors.width(), dim.index_to_column(first_connected));
322  nested_minors.push(nested_minor_sequence::TWO_ROWS_ONE_COLUMN);
323  return separation();
324  }
325  else
326  {
327  assert (dim.is_column(connecting_start));
328  assert (dim.is_column(nearest_end));
329 
330  matroid_permute2(matroid, matrix, dim.index_to_column(connecting_start), nested_minors.width());
331  matroid_permute2(matroid, matrix, dim.index_to_column(nearest_end), nested_minors.width() + 1);
332  matroid_permute1(matroid, matrix, nested_minors.height(), dim.index_to_row(first_connected));
333  nested_minors.push(nested_minor_sequence::ONE_ROW_TWO_COLUMNS);
334  return separation();
335  }
336  }
337 
338  return separation();
339  }
340  else
341  {
343  std::pair <size_t, size_t> split(0, 0);
344 
345  std::vector <int> reachable(matrix.size1());
346  for (size_t row = 0; row < matrix.size1(); ++row)
347  {
348  const bipartite_graph_bfs_node& node = bfs_result[dim.row_to_index(row)];
349  int value = row < nested_minors.height() ? row - nested_minors.height() : (node.is_reachable() ? 2 : 1);
350  reachable[row] = value;
351  if (value < 2)
352  split.first++;
353  }
354  vector_less <int, std::less <int> > less(reachable, std::less <int>());
355 
356  permutation p(matrix.size1());
357  sort(p, less);
359 
360  reachable.resize(matrix.size2());
361  for (size_t column = 0; column < matrix.size2(); ++column)
362  {
363  const bipartite_graph_bfs_node& node = bfs_result[dim.column_to_index(column)];
364  int value = column < nested_minors.width() ? column - nested_minors.width() : (node.is_reachable() ? 2 : 1);
365  reachable[column] = value;
366  if (value < 2)
367  split.second++;
368  }
369 
370  p.reset(matrix.size2());
371  sort(p, less);
373  split.first--;
374  matroid_permute1(matroid, matrix, split.first, index);
375 
376  std::pair <size_t, size_t> witness(split.first, 0);
377  while (matrix(witness.first, witness.second) == 0)
378  {
379  assert (witness.second < nested_minors.width());
380  witness.second++;
381  }
382 
383  separation result(split, witness);
384  result.set_special_swap('r', index);
385  return result;
386  }
387  }
388 
402  template <typename MatroidType, typename MatrixType>
403  separation find_minor_sequence(MatroidType& matroid, MatrixType& matrix, nested_minor_sequence& nested_minors, matroid_element_set& extra_elements,
404  logger& log)
405  {
406  size_t cut = log.size();
407 
408  matroid_transposed <MatroidType> transposed_matroid(matroid);
409  matrix_transposed <MatrixType> transposed_matrix(matrix);
410 
411  vector_three_connectivity <MatrixType> column_three_connectivity(matrix, nested_minors.height(), nested_minors.width());
412  vector_three_connectivity <matrix_transposed <MatrixType> > row_three_connectivity(transposed_matrix, nested_minors.width(),
413  nested_minors.height());
414 
416  nested_minor_sequence_transposed <nested_minor_sequence> transposed_nested_minors(nested_minors);
417 
418  while (nested_minors.height() < matroid.size1() || nested_minors.width() != matroid.size2())
419  {
420  if (log.is_progressive())
421  {
422  log.erase(cut);
423  log.line() << " + " << nested_minors.size() << " EXT";
424  std::cout << log;
425  }
426 
427  assert (nested_minors.height() == row_three_connectivity.base());
428  assert (nested_minors.height() == column_three_connectivity.dimension());
429  assert (nested_minors.width() == row_three_connectivity.dimension());
430  assert (nested_minors.width() == column_three_connectivity.base());
431 
433  if (find_simple_row_extension(matroid, matrix, nested_minors, row_three_connectivity, column_three_connectivity))
434  {
435  continue;
436  }
437 
439  if (find_simple_row_extension(transposed_matroid, transposed_matrix, transposed_nested_minors, column_three_connectivity,
440  row_three_connectivity))
441  {
442  continue;
443  }
444 
445  size_t the_index = 0;
446  char type = find_parallel_or_unit_vector(matroid, matrix, nested_minors, row_three_connectivity, column_three_connectivity, the_index);
447  if (type == 0)
448  {
449  return separation(std::make_pair(nested_minors.height(), nested_minors.width()));
450  }
451  else if (type == 'r')
452  {
454  separation sep = find_elaborate_extension(matroid, matrix, nested_minors, row_three_connectivity, column_three_connectivity, the_index,
455  extra_elements);
456  if (sep.is_valid())
457  {
458  return sep;
459  }
460  }
461  else if (type == 'c')
462  {
464  separation sep = find_elaborate_extension(transposed_matroid, transposed_matrix, transposed_nested_minors, column_three_connectivity,
465  row_three_connectivity, the_index, extra_elements);
466  if (sep.is_valid())
467  return sep.transposed();
468  }
469  else
470  {
471  throw std::runtime_error("tu::find_minor_sequence: Invalid parallel/unit-vector type.");
472  }
473 
474  row_three_connectivity.reset(nested_minors.width(), nested_minors.height());
475  column_three_connectivity.reset(nested_minors.height(), nested_minors.width());
476  }
477 
478  if (log.is_progressive())
479  {
480  log.erase(cut);
481  log.line() << " + " << nested_minors.size() << " EXT";
482  std::cout << log;
483  }
484 
485  return separation();
486  }
487 
488 } /* namespace tu */
Definition: logger.hpp:19
bool is_progressive() const
Definition: logger.hpp:67
std::stringstream & line()
Definition: logger.hpp:131
size_t size() const
Definition: logger.hpp:108
void erase(size_t position)
Definition: logger.hpp:119
Definition: matrix_modified.hpp:14
Definition: matrix_transposed.hpp:47
Definition: matroid_transposed.hpp:14
Definition: matroid.hpp:22
size_t size1() const
Definition: matroid.hpp:77
size_t size2() const
Definition: matroid.hpp:86
name_type & name2(size_t index)
Definition: matroid.hpp:116
name_type & name1(size_t index)
Definition: matroid.hpp:96
Definition: nested_minor_sequence.hpp:154
Definition: nested_minor_sequence.hpp:16
size_t width() const
Definition: nested_minor_sequence.hpp:121
@ ONE_ROW_ONE_COLUMN
Definition: nested_minor_sequence.hpp:28
@ ONE_ROW
Definition: nested_minor_sequence.hpp:26
@ TWO_ROWS_ONE_COLUMN
Definition: nested_minor_sequence.hpp:29
@ ONE_ROW_TWO_COLUMNS
Definition: nested_minor_sequence.hpp:27
size_t size() const
Definition: nested_minor_sequence.hpp:130
size_t height() const
Definition: nested_minor_sequence.hpp:112
Definition: permutations.hpp:44
void reset(size_t new_size)
Definition: permutations.hpp:111
Definition: separation.hpp:18
separation transposed()
Definition: separation.cpp:161
bool is_valid() const
Definition: separation.hpp:125
void set_special_swap(char type, size_t index)
Definition: separation.hpp:149
Definition: vector_three_connectivity.hpp:10
void reset(size_t dimension, size_t base)
Definition: vector_three_connectivity.hpp:34
size_t base() const
Definition: vector_three_connectivity.hpp:78
size_t dimension() const
Definition: vector_three_connectivity.hpp:83
#define CMR_UNUSED(x)
Definition: env.h:24
Definition: algorithm.hpp:14
void sort(permutation &permutation, size_t first, size_t beyond, Less &less)
Definition: permutations.hpp:583
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
separation find_minor_sequence(MatroidType &matroid, MatrixType &matrix, nested_minor_sequence &nested_minors, matroid_element_set &extra_elements, logger &log)
Definition: find_minor_sequence.hpp:403
bool find_simple_row_extension(MatroidType &matroid, MatrixType &matrix, NestedMinorSequenceType &nested_minors, RowThreeConnectivity &row_three_connectivity, ColumnThreeConnectivity &column_three_connectivity)
Definition: find_minor_sequence.hpp:30
separation find_elaborate_extension(MatroidType &matroid, MatrixType &matrix, NestedMinorSequenceType &nested_minors, RowThreeConnectivity &row_three_connectivity, ColumnThreeConnectivity &column_three_connectivity, size_t index, matroid_element_set &extra_elements)
Definition: find_minor_sequence.hpp:190
void matroid_apply_row_permutation(MatroidType &matroid, MatrixType &matrix, const permutation &perm)
Definition: matroid_reorder.hpp:18
void matroid_permute1(matroid< NameType > &matroid, size_t index1, size_t index2)
Definition: matroid.hpp:162
void matroid_apply_column_permutation(MatroidType &matroid, MatrixType &matrix, const permutation &perm)
Definition: matroid_reorder.hpp:40
void matroid_permute2(matroid< NameType > &matroid, size_t index1, size_t index2)
Definition: matroid.hpp:192
void matroid_binary_pivot(matroid< NameType > &matroid, size_t i, size_t j)
Definition: matroid.hpp:222
char find_parallel_or_unit_vector(MatroidType &matroid, MatrixType &matrix, NestedMinorSequenceType &nested_minors, RowThreeConnectivity &row_three_connectivity, ColumnThreeConnectivity &column_three_connectivity, size_t &index)
Definition: find_minor_sequence.hpp:66
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
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
bool is_column(index_type index) const
Definition: bipartite_graph_bfs.hpp:98
Definition: find_minor_sequence.hpp:109
@ ZERO
Definition: find_minor_sequence.hpp:114
@ END0
Definition: find_minor_sequence.hpp:116
int operator()(size_t i, size_t j, int value)
Definition: find_minor_sequence.hpp:142
@ BLOCK
Definition: find_minor_sequence.hpp:113
unsigned char index_type
Definition: find_minor_sequence.hpp:111
@ START
Definition: find_minor_sequence.hpp:115
int value_type
Definition: find_minor_sequence.hpp:110
@ END1
Definition: find_minor_sequence.hpp:117
elaborate_extension_matrix_modifier(const std::vector< index_type > &row_types, const std::vector< index_type > &column_types)
Definition: find_minor_sequence.hpp:127
Definition: comparators.hpp:108