File indexing completed on 2025-01-18 09:37:30
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef __IS_KURATOWSKI_SUBGRAPH_HPP__
0009 #define __IS_KURATOWSKI_SUBGRAPH_HPP__
0010
0011 #include <boost/config.hpp>
0012 #include <boost/tuple/tuple.hpp> //for tie
0013 #include <boost/property_map/property_map.hpp>
0014 #include <boost/graph/properties.hpp>
0015 #include <boost/graph/isomorphism.hpp>
0016 #include <boost/graph/adjacency_list.hpp>
0017
0018 #include <algorithm>
0019 #include <vector>
0020 #include <set>
0021
0022 namespace boost
0023 {
0024
0025 namespace detail
0026 {
0027
0028 template < typename Graph > Graph make_K_5()
0029 {
0030 typename graph_traits< Graph >::vertex_iterator vi, vi_end, inner_vi;
0031 Graph K_5(5);
0032 for (boost::tie(vi, vi_end) = vertices(K_5); vi != vi_end; ++vi)
0033 for (inner_vi = next(vi); inner_vi != vi_end; ++inner_vi)
0034 add_edge(*vi, *inner_vi, K_5);
0035 return K_5;
0036 }
0037
0038 template < typename Graph > Graph make_K_3_3()
0039 {
0040 typename graph_traits< Graph >::vertex_iterator vi, vi_end,
0041 bipartition_start, inner_vi;
0042 Graph K_3_3(6);
0043 bipartition_start = next(next(next(vertices(K_3_3).first)));
0044 for (boost::tie(vi, vi_end) = vertices(K_3_3); vi != bipartition_start;
0045 ++vi)
0046 for (inner_vi = bipartition_start; inner_vi != vi_end; ++inner_vi)
0047 add_edge(*vi, *inner_vi, K_3_3);
0048 return K_3_3;
0049 }
0050
0051 template < typename AdjacencyList, typename Vertex >
0052 void contract_edge(AdjacencyList& neighbors, Vertex u, Vertex v)
0053 {
0054
0055 neighbors[v].erase(
0056 std::remove(neighbors[v].begin(), neighbors[v].end(), u),
0057 neighbors[v].end());
0058
0059
0060 typedef
0061 typename AdjacencyList::value_type::iterator adjacency_iterator_t;
0062
0063 adjacency_iterator_t u_neighbor_end = neighbors[u].end();
0064 for (adjacency_iterator_t u_neighbor_itr = neighbors[u].begin();
0065 u_neighbor_itr != u_neighbor_end; ++u_neighbor_itr)
0066 {
0067 Vertex u_neighbor(*u_neighbor_itr);
0068 std::replace(neighbors[u_neighbor].begin(),
0069 neighbors[u_neighbor].end(), u, v);
0070 }
0071
0072
0073 neighbors[u].erase(
0074 std::remove(neighbors[u].begin(), neighbors[u].end(), v),
0075 neighbors[u].end());
0076
0077
0078 std::copy(neighbors[u].begin(), neighbors[u].end(),
0079 std::back_inserter(neighbors[v]));
0080
0081
0082 neighbors[u].clear();
0083 }
0084
0085 enum target_graph_t
0086 {
0087 tg_k_3_3,
0088 tg_k_5
0089 };
0090
0091 }
0092
0093 template < typename Graph, typename ForwardIterator, typename VertexIndexMap >
0094 bool is_kuratowski_subgraph(const Graph& g, ForwardIterator begin,
0095 ForwardIterator end, VertexIndexMap vm)
0096 {
0097
0098 typedef typename graph_traits< Graph >::vertex_descriptor vertex_t;
0099 typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t;
0100 typedef typename graph_traits< Graph >::edge_descriptor edge_t;
0101 typedef typename graph_traits< Graph >::edges_size_type e_size_t;
0102 typedef typename graph_traits< Graph >::vertices_size_type v_size_t;
0103 typedef typename std::vector< vertex_t > v_list_t;
0104 typedef typename v_list_t::iterator v_list_iterator_t;
0105 typedef iterator_property_map< typename std::vector< v_list_t >::iterator,
0106 VertexIndexMap >
0107 vertex_to_v_list_map_t;
0108
0109 typedef adjacency_list< vecS, vecS, undirectedS > small_graph_t;
0110
0111 detail::target_graph_t target_graph
0112 = detail::tg_k_3_3;
0113
0114 static small_graph_t K_5(detail::make_K_5< small_graph_t >());
0115
0116 static small_graph_t K_3_3(detail::make_K_3_3< small_graph_t >());
0117
0118 v_size_t n_vertices(num_vertices(g));
0119 v_size_t max_num_edges(3 * n_vertices - 5);
0120
0121 std::vector< v_list_t > neighbors_vector(n_vertices);
0122 vertex_to_v_list_map_t neighbors(neighbors_vector.begin(), vm);
0123
0124 e_size_t count = 0;
0125 for (ForwardIterator itr = begin; itr != end; ++itr)
0126 {
0127
0128 if (count++ > max_num_edges)
0129 return false;
0130
0131 edge_t e(*itr);
0132 vertex_t u(source(e, g));
0133 vertex_t v(target(e, g));
0134
0135 neighbors[u].push_back(v);
0136 neighbors[v].push_back(u);
0137 }
0138
0139 for (v_size_t max_size = 2; max_size < 5; ++max_size)
0140 {
0141
0142 vertex_iterator_t vi, vi_end;
0143 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0144 {
0145 vertex_t v(*vi);
0146
0147
0148
0149 if (max_size == 4 && neighbors[v].size() == 3)
0150 {
0151 if (neighbors[neighbors[v][0]].size()
0152 + neighbors[neighbors[v][1]].size()
0153 + neighbors[neighbors[v][2]].size()
0154 < 11
0155 )
0156 continue;
0157 }
0158
0159 while (neighbors[v].size() > 0 && neighbors[v].size() < max_size)
0160 {
0161
0162
0163
0164
0165
0166
0167 bool neighbor_sets_intersect = false;
0168
0169 vertex_t min_u = graph_traits< Graph >::null_vertex();
0170 vertex_t u;
0171 v_list_iterator_t v_neighbor_end = neighbors[v].end();
0172 for (v_list_iterator_t v_neighbor_itr = neighbors[v].begin();
0173 v_neighbor_itr != v_neighbor_end; ++v_neighbor_itr)
0174 {
0175 neighbor_sets_intersect = false;
0176 u = *v_neighbor_itr;
0177 v_list_iterator_t u_neighbor_end = neighbors[u].end();
0178 for (v_list_iterator_t u_neighbor_itr
0179 = neighbors[u].begin();
0180 u_neighbor_itr != u_neighbor_end
0181 && !neighbor_sets_intersect;
0182 ++u_neighbor_itr)
0183 {
0184 for (v_list_iterator_t inner_v_neighbor_itr
0185 = neighbors[v].begin();
0186 inner_v_neighbor_itr != v_neighbor_end;
0187 ++inner_v_neighbor_itr)
0188 {
0189 if (*u_neighbor_itr == *inner_v_neighbor_itr)
0190 {
0191 neighbor_sets_intersect = true;
0192 break;
0193 }
0194 }
0195 }
0196 if (!neighbor_sets_intersect
0197 && (min_u == graph_traits< Graph >::null_vertex()
0198 || neighbors[u].size() < neighbors[min_u].size()))
0199 {
0200 min_u = u;
0201 }
0202 }
0203
0204 if (min_u == graph_traits< Graph >::null_vertex())
0205
0206
0207
0208 break;
0209 else
0210 u = min_u;
0211
0212 detail::contract_edge(neighbors, u, v);
0213
0214 }
0215
0216 }
0217
0218 if (max_size == 3)
0219 {
0220
0221 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0222 if (neighbors[*vi].size() == 4)
0223 {
0224 target_graph = detail::tg_k_5;
0225 break;
0226 }
0227
0228 if (target_graph == detail::tg_k_3_3)
0229 break;
0230 }
0231
0232 }
0233
0234
0235
0236 v_list_t main_vertices;
0237 vertex_iterator_t vi, vi_end;
0238
0239 for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
0240 {
0241 if (!neighbors[*vi].empty())
0242 main_vertices.push_back(*vi);
0243 }
0244
0245
0246
0247 small_graph_t contracted_graph(main_vertices.size());
0248 std::map< vertex_t,
0249 typename graph_traits< small_graph_t >::vertex_descriptor >
0250 contracted_vertex_map;
0251
0252 typename v_list_t::iterator itr, itr_end;
0253 itr_end = main_vertices.end();
0254 typename graph_traits< small_graph_t >::vertex_iterator si
0255 = vertices(contracted_graph).first;
0256
0257 for (itr = main_vertices.begin(); itr != itr_end; ++itr, ++si)
0258 {
0259 contracted_vertex_map[*itr] = *si;
0260 }
0261
0262 typename v_list_t::iterator jtr, jtr_end;
0263 for (itr = main_vertices.begin(); itr != itr_end; ++itr)
0264 {
0265 jtr_end = neighbors[*itr].end();
0266 for (jtr = neighbors[*itr].begin(); jtr != jtr_end; ++jtr)
0267 {
0268 if (get(vm, *itr) < get(vm, *jtr))
0269 {
0270 add_edge(contracted_vertex_map[*itr],
0271 contracted_vertex_map[*jtr], contracted_graph);
0272 }
0273 }
0274 }
0275
0276 if (target_graph == detail::tg_k_5)
0277 {
0278 return boost::isomorphism(K_5, contracted_graph);
0279 }
0280 else
0281 {
0282 return boost::isomorphism(K_3_3, contracted_graph);
0283 }
0284 }
0285
0286 template < typename Graph, typename ForwardIterator >
0287 bool is_kuratowski_subgraph(
0288 const Graph& g, ForwardIterator begin, ForwardIterator end)
0289 {
0290 return is_kuratowski_subgraph(g, begin, end, get(vertex_index, g));
0291 }
0292
0293 }
0294
0295 #endif