File indexing completed on 2025-01-18 09:37:24
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_GRAPH_CLIQUE_HPP
0008 #define BOOST_GRAPH_CLIQUE_HPP
0009
0010 #include <vector>
0011 #include <deque>
0012 #include <boost/config.hpp>
0013
0014 #include <boost/concept/assert.hpp>
0015
0016 #include <boost/graph/graph_concepts.hpp>
0017 #include <boost/graph/lookup_edge.hpp>
0018
0019 #include <boost/concept/detail/concept_def.hpp>
0020 namespace boost
0021 {
0022 namespace concepts
0023 {
0024 BOOST_concept(CliqueVisitor, (Visitor)(Clique)(Graph))
0025 {
0026 BOOST_CONCEPT_USAGE(CliqueVisitor) { vis.clique(k, g); }
0027
0028 private:
0029 Visitor vis;
0030 Graph g;
0031 Clique k;
0032 };
0033 }
0034 using concepts::CliqueVisitorConcept;
0035 }
0036 #include <boost/concept/detail/concept_undef.hpp>
0037
0038 namespace boost
0039 {
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 struct clique_visitor
0091 {
0092 template < typename VertexSet, typename Graph >
0093 void clique(const VertexSet&, Graph&)
0094 {
0095 }
0096 };
0097
0098
0099
0100
0101
0102 struct max_clique_visitor
0103 {
0104 max_clique_visitor(std::size_t& max) : maximum(max) {}
0105
0106 template < typename Clique, typename Graph >
0107 inline void clique(const Clique& p, const Graph& g)
0108 {
0109 BOOST_USING_STD_MAX();
0110 maximum = max BOOST_PREVENT_MACRO_SUBSTITUTION(maximum, p.size());
0111 }
0112 std::size_t& maximum;
0113 };
0114
0115 inline max_clique_visitor find_max_clique(std::size_t& max)
0116 {
0117 return max_clique_visitor(max);
0118 }
0119
0120 namespace detail
0121 {
0122 template < typename Graph >
0123 inline bool is_connected_to_clique(const Graph& g,
0124 typename graph_traits< Graph >::vertex_descriptor u,
0125 typename graph_traits< Graph >::vertex_descriptor v,
0126 typename graph_traits< Graph >::undirected_category)
0127 {
0128 return lookup_edge(u, v, g).second;
0129 }
0130
0131 template < typename Graph >
0132 inline bool is_connected_to_clique(const Graph& g,
0133 typename graph_traits< Graph >::vertex_descriptor u,
0134 typename graph_traits< Graph >::vertex_descriptor v,
0135 typename graph_traits< Graph >::directed_category)
0136 {
0137
0138
0139
0140
0141
0142 return lookup_edge(u, v, g).second && lookup_edge(v, u, g).second;
0143 }
0144
0145 template < typename Graph, typename Container >
0146 inline void filter_unconnected_vertices(const Graph& g,
0147 typename graph_traits< Graph >::vertex_descriptor v,
0148 const Container& in, Container& out)
0149 {
0150 BOOST_CONCEPT_ASSERT((GraphConcept< Graph >));
0151
0152 typename graph_traits< Graph >::directed_category cat;
0153 typename Container::const_iterator i, end = in.end();
0154 for (i = in.begin(); i != end; ++i)
0155 {
0156 if (is_connected_to_clique(g, v, *i, cat))
0157 {
0158 out.push_back(*i);
0159 }
0160 }
0161 }
0162
0163 template < typename Graph,
0164 typename Clique,
0165 typename Container,
0166 typename Visitor >
0167 void extend_clique(const Graph& g, Clique& clique, Container& cands,
0168 Container& nots, Visitor vis, std::size_t min)
0169 {
0170 BOOST_CONCEPT_ASSERT((GraphConcept< Graph >));
0171 BOOST_CONCEPT_ASSERT((CliqueVisitorConcept< Visitor, Clique, Graph >));
0172 typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
0173
0174
0175
0176
0177 {
0178 typename Container::iterator ni, nend = nots.end();
0179 typename Container::iterator ci, cend = cands.end();
0180 for (ni = nots.begin(); ni != nend; ++ni)
0181 {
0182 for (ci = cands.begin(); ci != cend; ++ci)
0183 {
0184
0185 if (!lookup_edge(*ni, *ci, g).second)
0186 break;
0187 }
0188
0189
0190 if (ci == cend)
0191 break;
0192 }
0193
0194 if (ni != nend)
0195 return;
0196 }
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223 typename Container::iterator i, j;
0224 for (i = cands.begin(); i != cands.end();)
0225 {
0226 Vertex candidate = *i;
0227
0228
0229
0230
0231 clique.push_back(candidate);
0232
0233
0234 i = cands.erase(i);
0235
0236
0237
0238
0239
0240 Container new_cands, new_nots;
0241 filter_unconnected_vertices(g, candidate, cands, new_cands);
0242 filter_unconnected_vertices(g, candidate, nots, new_nots);
0243
0244 if (new_cands.empty() && new_nots.empty())
0245 {
0246
0247
0248
0249 if (clique.size() >= min)
0250 {
0251 vis.clique(clique, g);
0252 }
0253 }
0254 else
0255 {
0256
0257 extend_clique(g, clique, new_cands, new_nots, vis, min);
0258 }
0259
0260
0261
0262 nots.push_back(candidate);
0263 clique.pop_back();
0264 }
0265 }
0266 }
0267
0268 template < typename Graph, typename Visitor >
0269 inline void bron_kerbosch_all_cliques(
0270 const Graph& g, Visitor vis, std::size_t min)
0271 {
0272 BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< Graph >));
0273 BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >));
0274 BOOST_CONCEPT_ASSERT(
0275 (AdjacencyMatrixConcept< Graph >));
0276 typedef typename graph_traits< Graph >::vertex_descriptor Vertex;
0277 typedef typename graph_traits< Graph >::vertex_iterator VertexIterator;
0278 typedef std::vector< Vertex > VertexSet;
0279 typedef std::deque< Vertex > Clique;
0280 BOOST_CONCEPT_ASSERT((CliqueVisitorConcept< Visitor, Clique, Graph >));
0281
0282
0283
0284
0285 VertexIterator i, end;
0286 boost::tie(i, end) = vertices(g);
0287 VertexSet cands(i, end);
0288 VertexSet nots;
0289
0290 Clique clique;
0291 detail::extend_clique(g, clique, cands, nots, vis, min);
0292 }
0293
0294
0295
0296 template < typename Graph, typename Visitor >
0297 inline void bron_kerbosch_all_cliques(const Graph& g, Visitor vis)
0298 {
0299 bron_kerbosch_all_cliques(g, vis, 2);
0300 }
0301
0302 template < typename Graph >
0303 inline std::size_t bron_kerbosch_clique_number(const Graph& g)
0304 {
0305 std::size_t ret = 0;
0306 bron_kerbosch_all_cliques(g, find_max_clique(ret));
0307 return ret;
0308 }
0309
0310 }
0311
0312 #endif