3 #include <boost/graph/bipartite.hpp>
4 #include <boost/graph/detail/set_adaptor.hpp>
5 #include <boost/graph/filtered_graph.hpp>
6 #include <boost/graph/connected_components.hpp>
7 #include <boost/graph/biconnected_components.hpp>
8 #include <boost/property_map/property_map.hpp>
14 #include <boost/graph/adjacency_list_io.hpp>
31 template <
typename Matro
idType,
typename MatrixType>
33 const size_t minor_width,
const size_t row)
38 for (
size_t c = 0; c < minor_width; ++c)
40 if (matrix(row, c) != 0)
50 for (
size_t r = 0; r < minor_height; ++r)
53 for (
size_t c = 0; c < minor_width; ++c)
55 if (matrix(r, c) != matrix(row, c))
67 throw std::logic_error(
"find_parallel_to_row did not find any parallel / unit vector!");
74 template <
typename Graph>
86 graph_(NULL), articulation_vertex_(NULL), evil_edges_(NULL)
100 graph_(graph), articulation_vertex_(articulation_vertex), evil_edges_(evil_edges)
111 template <
typename Edge>
114 if (evil_edges_->find(e) != evil_edges_->end())
117 if (boost::source(e, *graph_) == *articulation_vertex_)
120 if (boost::target(e, *graph_) == *articulation_vertex_)
141 template <
typename Graph,
typename Vertex,
typename EdgeSet>
143 const Vertex* articulation_vertex,
const EdgeSet* evil_edges)
145 return articulation_edge_filter<Graph> (graph, articulation_vertex, evil_edges);
161 template <
typename Matro
idType,
typename MatrixType>
165 typedef boost::graph_traits<matroid_graph> traits;
168 std::map<int, traits::edge_descriptor> reverse_element_map;
170 typename traits::edge_iterator edge_iter, edge_end;
171 for (boost::tie(edge_iter, edge_end) = boost::edges(graph); edge_iter != edge_end; ++edge_iter)
173 reverse_element_map[element_map[*edge_iter]] = *edge_iter;
177 switch (extension_type)
186 traits::vertex_descriptor first_vertex1 = boost::source(reverse_element_map[first_edge_element], graph);
187 traits::vertex_descriptor first_vertex2 = boost::target(reverse_element_map[first_edge_element], graph);
188 traits::vertex_descriptor second_vertex1 = boost::source(reverse_element_map[second_edge_element], graph);
189 traits::vertex_descriptor second_vertex2 = boost::target(reverse_element_map[second_edge_element], graph);
191 if (first_vertex1 == second_vertex2)
192 std::swap(second_vertex1, second_vertex2);
193 if (first_vertex2 == second_vertex1)
194 std::swap(first_vertex1, first_vertex2);
195 if (first_vertex2 == second_vertex2)
197 std::swap(first_vertex1, first_vertex2);
198 std::swap(second_vertex1, second_vertex2);
200 if (first_vertex1 != second_vertex1)
205 boost::remove_edge(reverse_element_map[first_edge_element], graph);
206 boost::remove_edge(reverse_element_map[second_edge_element], graph);
210 traits::vertex_descriptor first_breaker = boost::add_vertex(graph);
211 traits::vertex_descriptor second_breaker = boost::add_vertex(graph);
215 boost::add_edge(first_vertex2, first_breaker, first_edge_element, graph);
216 boost::add_edge(first_breaker, first_vertex1,
matroid.
name1(minor_height), graph);
217 boost::add_edge(second_vertex2, second_breaker, second_edge_element, graph);
218 boost::add_edge(second_breaker, second_vertex1,
matroid.
name1(minor_height + 1), graph);
219 boost::add_edge(first_breaker, second_breaker,
matroid.
name2(minor_width), graph);
227 minor_width, minor_height, minor_width);
229 minor_width, minor_height, minor_width + 1);
233 traits::vertex_descriptor first_vertex1 = boost::source(reverse_element_map[first_edge_element], graph);
234 traits::vertex_descriptor first_vertex2 = boost::target(reverse_element_map[first_edge_element], graph);
235 traits::vertex_descriptor second_vertex1 = boost::source(reverse_element_map[second_edge_element], graph);
236 traits::vertex_descriptor second_vertex2 = boost::target(reverse_element_map[second_edge_element], graph);
238 if (first_vertex1 == second_vertex2)
239 std::swap(second_vertex1, second_vertex2);
240 if (first_vertex2 == second_vertex1)
241 std::swap(first_vertex1, first_vertex2);
242 if (first_vertex2 == second_vertex2)
244 std::swap(first_vertex1, first_vertex2);
245 std::swap(second_vertex1, second_vertex2);
247 if (first_vertex1 != second_vertex1)
252 traits::vertex_descriptor additional_vertex = boost::add_vertex(graph);
256 boost::add_edge(first_vertex2, additional_vertex,
matroid.
name2(minor_width), graph);
257 boost::add_edge(second_vertex2, additional_vertex,
matroid.
name2(minor_width + 1), graph);
258 boost::add_edge(first_vertex1, additional_vertex,
matroid.
name1(minor_height), graph);
267 minor_width, minor_height, minor_width);
271 traits::vertex_descriptor row_vertex1 = boost::source(reverse_element_map[row_edge_element], graph);
272 traits::vertex_descriptor row_vertex2 = boost::target(reverse_element_map[row_edge_element], graph);
273 traits::vertex_descriptor column_vertex1 = boost::source(reverse_element_map[column_edge_element], graph);
274 traits::vertex_descriptor column_vertex2 = boost::target(reverse_element_map[column_edge_element], graph);
276 if (row_vertex1 == column_vertex2)
277 std::swap(column_vertex1, column_vertex2);
278 if (row_vertex2 == column_vertex1)
279 std::swap(row_vertex1, row_vertex2);
280 if (row_vertex2 == column_vertex2)
282 std::swap(row_vertex1, row_vertex2);
283 std::swap(column_vertex1, column_vertex2);
285 if (row_vertex1 != column_vertex1)
290 boost::remove_edge(reverse_element_map[row_edge_element], graph);
294 traits::vertex_descriptor row_breaker = boost::add_vertex(graph);
298 boost::add_edge(row_vertex2, row_breaker, row_edge_element, graph);
299 boost::add_edge(row_breaker, row_vertex1,
matroid.
name1(minor_height), graph);
300 boost::add_edge(row_breaker, column_vertex2,
matroid.
name2(minor_width), graph);
307 typedef std::set<traits::edge_descriptor> edge_set_t;
308 typedef boost::filtered_graph<matroid_graph, boost::is_in_subset<edge_set_t> > edge_subset_graph_t;
312 for (
size_t r = 0; r < minor_height; ++r)
314 if (matrix(r, minor_width) == 1)
319 std::vector<traits::vertex_descriptor> path;
321 edge_subset_graph_t edge_subset_graph(graph, boost::is_in_subset<edge_set_t>(edge_set));
322 if (!
tu::util::is_path(edge_subset_graph, boost::get(boost::vertex_index, edge_subset_graph), path))
327 boost::add_edge(path[0], path[path.size() - 1],
matroid.
name2(minor_width), graph);
333 typedef traits::edge_descriptor edge_t;
334 typedef traits::vertex_descriptor vertex_t;
335 typedef std::set<vertex_t> vertex_set;
336 typedef std::set<edge_t> edge_set;
337 typedef std::vector<vertex_t> vertex_vector_t;
338 typedef std::vector<edge_t> edge_vector_t;
340 typedef boost::vec_adj_list_vertex_id_map<boost::no_property, traits::vertices_size_type> IndexMap;
341 IndexMap index_map = boost::get(boost::vertex_index, graph);
346 for (
size_t c = 0; c < minor_width; ++c)
348 if (matrix(minor_height, c) != 0)
349 one_edges.insert(reverse_element_map[
matroid.
name2(c)]);
352 traits::vertex_descriptor the_vertex = traits::null_vertex();
358 traits::vertex_descriptor new_vertex = boost::add_vertex(graph);
359 boost::add_edge(the_vertex, new_vertex,
matroid.
name1(minor_height), graph);
363 for (edge_set::const_iterator edge_iter = one_edges.begin(); edge_iter != one_edges.end(); ++edge_iter)
365 traits::edge_descriptor edge = *edge_iter;
366 traits::vertex_descriptor other_vertex = boost::source(edge, graph);
367 if (other_vertex == the_vertex)
368 other_vertex = boost::target(edge, graph);
369 int name = element_map[edge];
370 boost::remove_edge(the_vertex, other_vertex, graph);
371 boost::add_edge(new_vertex, other_vertex, name, graph);
379 std::vector<size_t> common_vertex_count(boost::num_vertices(graph), 0);
380 for (
size_t c = 0; c < minor_width; ++c)
382 if (matrix(minor_height, c) == 0)
386 for (
size_t r = 0; r < minor_height; ++r)
388 if (matrix(r, c) == 1)
395 for (
typename vertex_set::const_iterator iter = vertices.begin(); iter != vertices.end(); ++iter)
397 common_vertex_count[boost::get(index_map, *iter)]++;
403 vertex_vector_t articulation_points;
404 boost::articulation_points(boost::make_filtered_graph(graph, boost::is_not_in_subset<edge_set>(one_edges)),
405 std::back_inserter(articulation_points));
407 std::vector<traits::vertex_descriptor> the_vertex_candidates;
408 the_vertex = traits::null_vertex();
409 for (vertex_vector_t::const_iterator iter = articulation_points.begin(); iter != articulation_points.end();
412 if (common_vertex_count[boost::get(index_map, *iter)] == one_edges.size())
414 the_vertex_candidates.push_back(*iter);
418 if (the_vertex_candidates.empty() || the_vertex_candidates.size() > 2)
421 for (vertex_vector_t::const_iterator iter = the_vertex_candidates.begin(); iter != the_vertex_candidates.end();
428 vertex_set articulation_set;
429 articulation_set.insert(the_vertex);
430 std::vector<size_t> component_vector(boost::num_vertices(graph));
432 size_t num_components = boost::connected_components(
434 boost::is_not_in_subset<vertex_set>(articulation_set)),
435 boost::make_iterator_property_map(component_vector.begin(), index_map));
438 assert(num_components >= 2);
440 typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS> component_graph_t;
441 component_graph_t component_graph(num_components);
444 for (
typename edge_set::const_iterator iter = one_edges.begin(); iter != one_edges.end(); ++iter)
446 typename boost::graph_traits<component_graph_t>::vertex_descriptor source, target;
447 source = boost::source(*iter, graph);
448 target = boost::target(*iter, graph);
449 if (source == the_vertex || target == the_vertex)
452 size_t source_component = component_vector[boost::get(index_map, source)];
453 size_t target_component = component_vector[boost::get(index_map, target)];
455 if (source_component == target_component)
462 boost::add_edge(boost::vertex(source_component, component_graph),
463 boost::vertex(target_component, component_graph), component_graph);
469 boost::one_bit_color_map<boost::vec_adj_list_vertex_id_map<boost::no_property, traits::vertices_size_type> > bipartition(
470 num_components, boost::get(boost::vertex_index, component_graph));
472 if (!boost::is_bipartite(component_graph, boost::get(boost::vertex_index, component_graph), bipartition))
477 for (
size_t i = 0; i < component_vector.size(); ++i)
479 if (boost::vertex(i, graph) == the_vertex)
483 vertex_t new_vertex = boost::add_vertex(graph);
485 edge_vector_t reconnect_edges;
486 typename traits::out_edge_iterator out_edge_iter, out_edge_end;
487 for (boost::tie(out_edge_iter, out_edge_end) = boost::incident_edges(the_vertex, graph);
488 out_edge_iter != out_edge_end; ++out_edge_iter)
490 vertex_t incident_vertex = boost::target(*out_edge_iter, graph);
492 bool reconnect = boost::get(bipartition,
493 boost::vertex(component_vector[boost::get(index_map, incident_vertex)], component_graph))
494 != boost::one_bit_white;
496 if (one_edges.find(*out_edge_iter) != one_edges.end())
497 reconnect = !reconnect;
500 reconnect_edges.push_back(*out_edge_iter);
503 for (
typename edge_vector_t::const_iterator iter = reconnect_edges.begin(); iter != reconnect_edges.end();
509 boost::add_edge(the_vertex, new_vertex,
matroid.
name1(minor_height), graph);
518 throw std::logic_error(
"Unknown extension in graphicness test.");
532 template <
typename Matro
idType,
typename MatrixType,
typename NestedMinorSequenceType>
534 const NestedMinorSequenceType& nested_minors,
size_t& largest_graphic_minor)
536 typedef boost::graph_traits<matroid_graph>::vertex_descriptor vertex_descriptor;
540 largest_graphic_minor = 0;
543 vertex_descriptor center_vertex = boost::vertex(0, *graph);
544 vertex_descriptor border_vertex1 = boost::vertex(1, *graph);
545 vertex_descriptor border_vertex2 = boost::vertex(2, *graph);
546 vertex_descriptor border_vertex3 = boost::vertex(3, *graph);
548 boost::add_edge(center_vertex, border_vertex1,
matroid.
name1(0), *graph);
549 boost::add_edge(center_vertex, border_vertex2,
matroid.
name1(1), *graph);
550 boost::add_edge(center_vertex, border_vertex3,
matroid.
name2(2), *graph);
551 boost::add_edge(border_vertex1, border_vertex2,
matroid.
name2(0), *graph);
552 boost::add_edge(border_vertex1, border_vertex3,
matroid.
name2(1), *graph);
553 boost::add_edge(border_vertex2, border_vertex3,
matroid.
name1(2), *graph);
555 size_t minor_height = 3;
556 size_t minor_width = 3;
558 for (
size_t i = 0; i < nested_minors.size(); ++i)
560 if (!
extend_graph(*graph,
matroid, matrix, minor_height, minor_width, nested_minors.get_extension(i)))
566 minor_height += nested_minors.get_extension_height(i);
567 minor_width += nested_minors.get_extension_width(i);
568 largest_graphic_minor++;
Definition: matroid.hpp:22
name_type & name2(size_t index)
Definition: matroid.hpp:116
name_type & name1(size_t index)
Definition: matroid.hpp:96
extension_type
Definition: nested_minor_sequence.hpp:24
@ 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_COLUMN
Definition: nested_minor_sequence.hpp:30
@ ONE_ROW_TWO_COLUMNS
Definition: nested_minor_sequence.hpp:27
bool find_star_vertex(const Graph &graph, const IndexMap index_map, Vertex &vertex)
Definition: graph_utils.hpp:220
bool is_path(const Graph &graph, const IndexMap index_map, VertexSequence &path)
Definition: graph_utils.hpp:151
void used_vertices(const Graph &graph, VertexSet &vertex_set)
Definition: graph_utils.hpp:296
void reconnect_edge(Graph &graph, typename boost::graph_traits< Graph >::edge_descriptor edge, typename boost::graph_traits< Graph >::vertex_descriptor old_vertex, typename boost::graph_traits< Graph >::vertex_descriptor new_vertex)
Definition: graph_utils.hpp:63
Definition: algorithm.hpp:14
matroid_graph * construct_matroid_graph(const MatroidType &matroid, const MatrixType &matrix, const NestedMinorSequenceType &nested_minors, size_t &largest_graphic_minor)
Definition: graphicness.hpp:533
boost::property_map< matroid_graph, edge_matroid_element_t >::type matroid_element_map
Definition: matroid_graph.hpp:45
bool extend_graph(matroid_graph &graph, const MatroidType &matroid, const MatrixType &matrix, const size_t minor_height, const size_t minor_width, const nested_minor_sequence::extension_type extension_type)
Definition: graphicness.hpp:162
matroid_transposed< MatroidType > make_transposed_matroid(MatroidType &matroid)
Definition: matroid_transposed.hpp:117
struct articulation_edge_filter< Graph > make_articulation_edge_filter(const Graph *graph, const Vertex *articulation_vertex, const EdgeSet *evil_edges)
Definition: graphicness.hpp:142
int find_parallel_to_row(const MatroidType &matroid, const MatrixType &matrix, const size_t minor_height, const size_t minor_width, const size_t row)
Definition: graphicness.hpp:32
matrix_transposed< MatrixType > make_transposed_matrix(MatrixType &matrix)
Definition: matrix_transposed.hpp:148
@ edge_matroid_element
Definition: matroid_graph.hpp:17
boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS, boost::no_property, matroid_element_property > matroid_graph
Definition: matroid_graph.hpp:21
Definition: graphicness.hpp:76
articulation_edge_filter(const Graph *graph, const vertex_descriptor *articulation_vertex, const edge_set *evil_edges)
Definition: graphicness.hpp:98
articulation_edge_filter()
Definition: graphicness.hpp:85
boost::graph_traits< Graph >::vertex_descriptor vertex_descriptor
Definition: graphicness.hpp:77
std::set< edge_descriptor > edge_set
Definition: graphicness.hpp:79
boost::graph_traits< Graph >::edge_descriptor edge_descriptor
Definition: graphicness.hpp:78
bool operator()(const Edge &e) const
Definition: graphicness.hpp:112