3 #include "matroid_decomposition.hpp"
4 #include "find_wheel_minor.hpp"
5 #include "matroid_separate.hpp"
6 #include "nested_minor_sequence.hpp"
7 #include "find_minor_sequence.hpp"
8 #include "graphicness.hpp"
10 #include "enumeration.hpp"
17 template <
typename Matro
idType,
typename MatrixType>
19 matroid_element_set extra_elements,
bool construct_decomposition, logger& log);
21 template <
typename Matro
idType,
typename MatrixType>
23 matrix_permuted<MatrixType>& permuted_matrix, nested_minor_sequence& nested_minors,
24 matroid_element_set extra_elements,
bool construct_decomposition, logger& log)
26 separation sep = find_minor_sequence(permuted_matroid, permuted_matrix, nested_minors, extra_elements, log);
29 if (log.is_progressive())
31 log.line() <<
" --> " << (sep.rank() + 1) <<
"-SEP";
32 std::cout << log << std::endl;
36 else if (log.is_verbose())
38 std::cout <<
"Found a " << (sep.rank() + 1) <<
"-separation instead." << std::endl;
41 integer_matroid upper_left_matroid;
42 integer_matrix upper_left_matrix;
43 integer_matroid lower_right_matroid;
44 integer_matrix lower_right_matrix;
46 sep.create_components(permuted_matroid, permuted_matrix, upper_left_matroid, upper_left_matrix,
47 lower_right_matroid, lower_right_matrix);
51 std::cout <<
"Summands are " << upper_left_matrix.size1() <<
" x " << upper_left_matrix.size2() <<
" and "
52 << lower_right_matrix.size1() <<
" x " << lower_right_matrix.size2() <<
"." << std::endl;
56 matroid_element_set upper_left_extra_elements, lower_right_extra_elements;
59 matroid_element_set upper_left_elements = upper_left_matroid.get_elements();
60 matroid_element_set lower_right_elements = lower_right_matroid.get_elements();
62 std::set_difference(extra_elements.begin(), extra_elements.end(), lower_right_elements.begin(),
63 lower_right_elements.end(), std::inserter(upper_left_extra_elements, upper_left_extra_elements.end()));
64 std::set_difference(extra_elements.begin(), extra_elements.end(), upper_left_elements.begin(),
65 upper_left_elements.end(), std::inserter(lower_right_extra_elements, lower_right_extra_elements.end()));
69 std::copy(extra_elements.begin(), extra_elements.end(), std::inserter(upper_left_extra_elements,
70 upper_left_extra_elements.end()));
71 std::copy(extra_elements.begin(), extra_elements.end(), std::inserter(lower_right_extra_elements,
72 lower_right_extra_elements.end()));
75 matroid_permuted<integer_matroid> permuted_upper_left_matroid(upper_left_matroid);
76 matrix_permuted<integer_matrix> permuted_upper_left_matrix(upper_left_matrix);
78 if (sep.has_special_swap())
80 if (sep.has_special_row_swap())
81 matroid_permute1(permuted_upper_left_matroid, permuted_upper_left_matrix, upper_left_matroid.size1() - 1,
82 sep.get_special_swap_index());
84 matroid_permute2(permuted_upper_left_matroid, permuted_upper_left_matrix, upper_left_matroid.size2() - 1,
85 sep.get_special_swap_index());
88 if (log.is_progressive())
90 log.line() <<
"(" << upper_left_matrix.size1() <<
" x " << upper_left_matrix.size2() <<
") W3";
93 else if (log.is_verbose())
95 std::cout <<
"Proceeding search for a sequence of nested minors in binary "
96 << permuted_upper_left_matroid.size1() <<
" x " << permuted_upper_left_matrix.size2() <<
" matroid."
101 permuted_upper_left_matroid, permuted_upper_left_matrix, nested_minors, upper_left_extra_elements,
102 construct_decomposition, log);
104 if (!construct_decomposition && !upper_left_result.first)
107 return std::pair<bool, decomposed_matroid*>(
false, NULL);
111 lower_right_matrix, lower_right_extra_elements, construct_decomposition, log);
113 if (log.is_progressive())
118 if (construct_decomposition)
120 int type = sep.rank() == 0 ?
static_cast<int>(decomposed_matroid_separator::ONE_SEPARATION)
121 :
static_cast<int>(decomposed_matroid_separator::TWO_SEPARATION);
123 return std::pair<bool, decomposed_matroid*>(lower_right_result.first && upper_left_result.first,
124 new decomposed_matroid_separator(upper_left_result.second, lower_right_result.second, type,
125 matroid_elements(permuted_matroid), extra_elements));
128 return std::pair<bool, decomposed_matroid*>(lower_right_result.first, NULL);
131 if (log.is_verbose())
133 std::cout <<
"Constructed sequence of " << (nested_minors.size() + 1)
134 <<
" 3-connected nested minors starting with W3." << std::endl;
137 size_t largest_graphic_minor = 0;
138 matroid_graph* graph = construct_matroid_graph(permuted_matroid, permuted_matrix, nested_minors,
139 largest_graphic_minor);
141 if (log.is_progressive())
143 log.line() << (graph == NULL ?
", NON-GRAPHIC" :
", GRAPHIC");
146 else if (log.is_verbose())
147 std::cout <<
"Matroid is " << (graph == NULL ?
"not " :
"") <<
"graphic." << std::endl;
149 if (!construct_decomposition && graph)
151 if (log.is_progressive())
154 std::cout <<
" --> REGULAR" << std::endl;
156 else if (log.is_verbose())
158 std::cout <<
"Graphic matroids are always regular." << std::endl;
162 return std::make_pair(
true, (decomposed_matroid*) NULL);
165 size_t largest_cographic_minor = 0;
166 matroid_graph* cograph = construct_matroid_graph(make_transposed_matroid(permuted_matroid), make_transposed_matrix(
167 permuted_matrix), make_transposed_nested_minor_sequence(nested_minors), largest_cographic_minor);
169 if (log.is_progressive())
171 log.line() << (cograph == NULL ?
", NON-COGRAPHIC" :
", COGRAPHIC");
174 else if (log.is_verbose())
176 std::cout <<
"Matroid is " << (cograph == NULL ?
"not " :
"") <<
"cographic." << std::endl;
179 if (!construct_decomposition && cograph)
181 if (log.is_progressive())
184 std::cout <<
" --> REGULAR" << std::endl;
186 else if (log.is_verbose())
188 std::cout <<
"Cographic matroids are always regular." << std::endl;
192 return std::make_pair(
true, (decomposed_matroid*) NULL);
195 if (construct_decomposition && (graph || cograph))
197 if (log.is_progressive())
200 std::cout << std::endl;
202 else if (log.is_verbose())
204 if (graph && cograph)
205 std::cout <<
"Planar matroids are always regular." << std::endl;
206 else if (graph && cograph == NULL)
207 std::cout <<
"Graphic matroids are always regular." << std::endl;
208 else if (graph == NULL && cograph)
209 std::cout <<
"Cographic matroids are always regular." << std::endl;
213 return std::make_pair(
true,
new decomposed_matroid_leaf(graph, cograph,
false,
214 matroid_elements(permuted_matroid), extra_elements));
217 if (is_r10(permuted_matrix))
219 if (log.is_progressive())
221 log.line() <<
", R10 --> REGULAR";
222 std::cout << log << std::endl;
225 else if (log.is_verbose())
227 std::cout <<
"Matroid is isomorphic to R10 and thus regular." << std::endl;
230 if (construct_decomposition)
232 return std::make_pair(
true,
new decomposed_matroid_leaf(NULL, NULL,
true, matroid_elements(permuted_matroid),
236 return std::make_pair(
true, (decomposed_matroid*) NULL);
240 if (log.is_progressive())
242 log.line() <<
", NOT R10";
245 else if (log.is_verbose())
246 std::cout <<
"Matroid is not isomorphic to R10." << std::endl;
249 size_t new_size = largest_graphic_minor > largest_cographic_minor ? largest_graphic_minor : largest_cographic_minor;
250 if (log.is_progressive())
252 log.line() <<
", (CO)GRAPHIC LEN: " << new_size;
255 else if (log.is_verbose())
256 std::cout <<
"Sequence is (co)graphic until N_" << new_size <<
"." << std::endl;
258 std::size_t minSize = 0;
259 std::size_t numElements = 6;
260 for (minSize = 0; minSize < nested_minors.size() && numElements < 8; ++minSize)
262 numElements += nested_minors.get_extension_height(minSize) + nested_minors.get_extension_width(minSize);
265 if (new_size < minSize)
268 if (log.is_progressive())
270 log.line() <<
", EXTENDING TO " << new_size;
273 else if (log.is_verbose())
274 std::cout <<
"Sequence extended by to N_" << new_size <<
" to achieve minimum size." << std::endl;
277 nested_minors.resize(new_size);
279 sep = enumerate_separations(permuted_matroid, permuted_matrix, nested_minors, extra_elements, log);
282 if (log.is_progressive())
284 log.line() <<
" --> " << (sep.rank() + 1) <<
"-SEP";
285 std::cout << log << std::endl;
289 else if (log.is_verbose())
291 std::cout <<
"Found a (3|4)-separation." << std::endl;
294 integer_matroid upper_left_matroid;
295 integer_matrix upper_left_matrix;
296 integer_matroid lower_right_matroid;
297 integer_matrix lower_right_matrix;
299 sep.create_components(permuted_matroid, permuted_matrix, upper_left_matroid, upper_left_matrix,
300 lower_right_matroid, lower_right_matrix);
302 if (log.is_verbose())
304 std::cout <<
"Summands are " << upper_left_matrix.size1() <<
" x " << upper_left_matrix.size2() <<
" and "
305 << lower_right_matrix.size1() <<
" x " << lower_right_matrix.size2() <<
"." << std::endl;
308 matroid_permuted<integer_matroid> permuted_upper_left_matroid(upper_left_matroid);
309 matrix_permuted<integer_matrix> permuted_upper_left_matrix(upper_left_matrix);
312 permuted_upper_left_matrix, extra_elements, construct_decomposition, log);
314 if (!construct_decomposition && !upper_left_result.first)
316 if (log.is_progressive())
320 return std::pair<bool, decomposed_matroid*>(
false, NULL);
324 lower_right_matrix, extra_elements, construct_decomposition, log);
326 if (log.is_progressive())
331 if (construct_decomposition)
332 return std::make_pair(lower_right_result.first && upper_left_result.first,
333 (decomposed_matroid *) (
new decomposed_matroid_separator(upper_left_result.second,
334 lower_right_result.second, decomposed_matroid_separator::THREE_SEPARATION, matroid_elements(
335 permuted_matroid), extra_elements)));
337 return std::pair<bool, decomposed_matroid*>(lower_right_result.first, NULL);
340 if (construct_decomposition)
341 return std::make_pair(
false,
new decomposed_matroid_leaf(NULL, NULL,
false, matroid_elements(permuted_matroid),
344 return std::make_pair(
false, (decomposed_matroid*) NULL);
355 template <
typename Matro
idType,
typename MatrixType>
358 assert(matroid.size1() <= 2 || matroid.size2() <= 2);
360 matroid_graph* graph =
new matroid_graph(matroid.size1() + 1);
362 if (matroid.size1() == 0)
364 for (
size_t column = 0; column < matroid.size2(); ++column)
366 boost::add_edge(boost::vertex(0, *graph), boost::vertex(0, *graph), matroid.name2(0), *graph);
369 else if (matroid.size2() == 0)
371 for (
size_t row = 0; row < matroid.size1(); ++row)
373 boost::add_edge(boost::vertex(row, *graph), boost::vertex(row + 1, *graph), matroid.name1(row), *graph);
376 else if (matroid.size1() >= 3 && matroid.size2() == 1)
378 size_t current_edge_vertex = 0;
379 size_t current_free_vertex = matroid.size1();
381 for (
size_t row = 0; row < matroid.size1(); ++row)
383 if (matrix(row, 0) == 0)
385 boost::add_edge(boost::vertex(current_free_vertex - 1, *graph), boost::vertex(current_free_vertex, *graph),
386 matroid.name1(row), *graph);
387 --current_free_vertex;
391 boost::add_edge(boost::vertex(current_edge_vertex, *graph), boost::vertex(current_edge_vertex + 1, *graph),
392 matroid.name1(row), *graph);
393 ++current_edge_vertex;
397 assert(current_edge_vertex == current_free_vertex);
399 boost::add_edge(boost::vertex(0, *graph), boost::vertex(current_edge_vertex, *graph), matroid.name2(0), *graph);
401 else if (matroid.size1() >= 3 && matroid.size2() == 2)
405 for (
size_t row = 0; row < matroid.size1(); ++row)
407 count[((matrix(row, 0) != 0) ? 2 : 0) + ((matrix(row, 1) != 0) ? 1 : 0)]++;
412 vertex[1] = count[1];
413 vertex[2] = vertex[1] + count[3];
414 vertex[3] = vertex[2] + count[2];
416 boost::add_edge(boost::vertex(vertex[0], *graph), boost::vertex(vertex[2], *graph), matroid.name2(1), *graph);
417 boost::add_edge(boost::vertex(vertex[1], *graph), boost::vertex(vertex[3], *graph), matroid.name2(0), *graph);
419 for (
size_t row = 0; row < matroid.size1(); ++row)
421 int element = matroid.name1(row);
422 switch (((matrix(row, 0) != 0) ? 2 : 0) + ((matrix(row, 1) != 0) ? 1 : 0))
425 boost::add_edge(boost::vertex(vertex[0], *graph), boost::vertex(vertex[0] + 1, *graph), element, *graph);
429 boost::add_edge(boost::vertex(vertex[2], *graph), boost::vertex(vertex[2] + 1, *graph), element, *graph);
433 boost::add_edge(boost::vertex(vertex[1], *graph), boost::vertex(vertex[1] + 1, *graph), element, *graph);
437 assert(matrix(row, 0) == 0 && matrix(row, 1) == 0);
438 boost::add_edge(boost::vertex(vertex[3], *graph), boost::vertex(vertex[3] + 1, *graph), element, *graph);
446 assert(matroid.size1() <= 2);
448 for (
size_t row = 0; row < matroid.size1(); ++row)
450 boost::add_edge(boost::vertex(row, *graph), boost::vertex(row + 1, *graph), matroid.name1(row), *graph);
453 for (
size_t column = 0; column < matroid.size2(); ++column)
455 size_t end_vertex, start_vertex = 0;
456 while (start_vertex < matroid.size1() && matrix(start_vertex, column) == 0)
460 end_vertex = start_vertex;
461 while (end_vertex < matroid.size1() && matrix(end_vertex, column) == 1)
466 boost::add_edge(boost::vertex(start_vertex, *graph), boost::vertex(end_vertex, *graph), matroid.name2(column),
483 template <
typename Matro
idType,
typename MatrixType>
485 matroid_element_set extra_elements,
bool construct_decomposition, logger& log)
487 assert(is_zero_one_matrix(matrix));
489 if (log.is_progressive())
492 log.line() <<
"(" << matrix.size1() <<
" x " << matrix.size2() <<
")";
495 else if (log.is_verbose())
497 std::cout <<
"Decomposing binary " << matrix.size1() <<
" x " << matrix.size2() <<
" matroid." << std::endl;
500 if (matroid.size1() <= 2 || matroid.size2() <= 2)
502 if (log.is_progressive())
504 log.line() <<
" TRIVIAL --> REGULAR";
505 std::cout << log << std::endl;
508 else if (log.is_verbose())
510 std::cout <<
"The matroid is trivial and thus regular." << std::endl;
513 if (construct_decomposition)
515 matroid_transposed<MatroidType> transposed_matroid(matroid);
516 matrix_transposed<MatrixType> transposed_matrix(matrix);
520 return std::make_pair(
true,
new decomposed_matroid_leaf(g, c,
false, matroid_elements(matroid), extra_elements));
524 return std::make_pair(
true, (decomposed_matroid*) NULL);
528 typedef matroid_permuted<MatroidType> permuted_matroid_type;
529 typedef matrix_permuted<MatrixType> permuted_marix_type;
531 permuted_matroid_type permuted_matroid(matroid);
532 permuted_marix_type permuted_matrix(matrix);
534 if (log.is_progressive())
539 else if (log.is_verbose())
541 std::cout <<
"Searching for a W3 minor." << std::endl;
546 separation sep = find_wheel_minor(permuted_matroid, permuted_matrix, extra_elements);
551 if (log.is_progressive())
553 log.line() <<
" --> " << (sep.rank() + 1) <<
"-separation";
554 std::cout << log << std::endl;
558 else if (log.is_verbose())
560 std::cout <<
"Found a " << (sep.rank() + 1) <<
"-separation instead." << std::endl;
563 integer_matroid upper_left_matroid;
564 integer_matrix upper_left_matrix;
565 integer_matroid lower_right_matroid;
566 integer_matrix lower_right_matrix;
568 sep.create_components(permuted_matroid, permuted_matrix, upper_left_matroid, upper_left_matrix,
569 lower_right_matroid, lower_right_matrix);
572 matroid_element_set upper_left_extra_elements, lower_right_extra_elements;
573 if (sep.rank() == 0 &&
false)
575 matroid_element_set upper_left_elements = upper_left_matroid.get_elements();
576 matroid_element_set lower_right_elements = lower_right_matroid.get_elements();
578 std::set_difference(extra_elements.begin(), extra_elements.end(), lower_right_elements.begin(),
579 lower_right_elements.end(), std::inserter(upper_left_extra_elements, upper_left_extra_elements.end()));
580 std::set_difference(extra_elements.begin(), extra_elements.end(), upper_left_elements.begin(),
581 upper_left_elements.end(), std::inserter(lower_right_extra_elements, lower_right_extra_elements.end()));
585 std::copy(extra_elements.begin(), extra_elements.end(), std::inserter(upper_left_extra_elements,
586 upper_left_extra_elements.end()));
587 std::copy(extra_elements.begin(), extra_elements.end(), std::inserter(lower_right_extra_elements,
588 lower_right_extra_elements.end()));
591 if (log.is_verbose())
593 std::cout <<
"Summands are " << upper_left_matrix.size1() <<
" x " << upper_left_matrix.size2() <<
" and "
594 << lower_right_matrix.size1() <<
" x " << lower_right_matrix.size2() <<
"." << std::endl;
598 upper_left_matrix, upper_left_extra_elements, construct_decomposition, log);
600 if (!construct_decomposition && !upper_left_result.first)
602 if (log.is_progressive())
606 return std::pair<bool, decomposed_matroid*>(
false, NULL);
610 lower_right_matrix, lower_right_extra_elements, construct_decomposition, log);
612 if (log.is_progressive())
617 if (construct_decomposition)
619 int type = sep.rank() == 0 ?
static_cast<int>(decomposed_matroid_separator::ONE_SEPARATION)
620 :
static_cast<int>(decomposed_matroid_separator::TWO_SEPARATION);
622 return std::pair<bool, decomposed_matroid*>(lower_right_result.first && upper_left_result.first,
623 new decomposed_matroid_separator(upper_left_result.second, lower_right_result.second, type,
624 matroid_elements(permuted_matroid), extra_elements));
627 return std::pair<bool, decomposed_matroid*>(lower_right_result.first && upper_left_result.first, NULL);
630 if (log.is_verbose())
632 std::cout <<
"Searching for a sequence of nested minors in binary " << permuted_matrix.size1() <<
" x "
633 << permuted_matrix.size2() <<
" matroid." << std::endl;
636 nested_minor_sequence nested_minors;
639 construct_decomposition, log);
Definition: algorithm.hpp:14
std::pair< bool, decomposed_matroid * > decompose_with_minor_sequence(matroid_permuted< MatroidType > &permuted_matroid, matrix_permuted< MatrixType > &permuted_matrix, nested_minor_sequence &nested_minors, matroid_element_set extra_elements, bool construct_decomposition, logger &log)
Definition: algorithm.hpp:22
std::pair< bool, decomposed_matroid * > decompose_binary_matroid(MatroidType &matroid, MatrixType &matrix, matroid_element_set extra_elements, bool construct_decomposition, logger &log)
Forward declaration.
Definition: algorithm.hpp:484
matroid_graph * construct_small_matroid_graph(MatroidType &matroid, MatrixType &matrix)
Definition: algorithm.hpp:356