Bron–Kerbosch algorithm
In computer science, the Bron–Kerbosch algorithm is an enumeration algorithm for finding maximal cliques in an undirected graph. That is, it lists all subsets of vertices with the two properties that each pair of vertices in one of the listed subsets is connected by an edge, and no listed subset can have any additional vertices added to it while preserving its complete connectivity. The Bron–Kerbosch algorithm was designed by Dutch scientists Coenraad Bron and Joep Kerbosch, who published its description in 1973. Although other algorithms for solving the clique problem have running times that are, in theory, better on inputs that have few maximal independent sets, the Bron–Kerbosch algorithm and subsequent improvements to it are frequently reported as being more efficient in practice than the alternatives. It is well-known and widely used in application areas of graph algorithms such as computational chemistry.
A contemporaneous algorithm of, although presented in different terms, can be viewed as being the same as the Bron–Kerbosch algorithm, as it generates the same recursive search tree.
Without pivoting
The basic form of the Bron–Kerbosch algorithm is a recursive backtracking algorithm that searches for all maximal cliques in a given graph G. More generally, given three disjoint sets of vertices R, P, and X, it finds the maximal cliques that include all of the vertices in R, some of the vertices in P, and none of the vertices in X. In each call to the algorithm, P and X are disjoint sets whose union consists of those vertices that form cliques when added to R. In other words, P ∪ X is the set of vertices which are joined to every element of R. When P and X are both empty there are no further elements that can be added to R, so R is a maximal clique and the algorithm outputs R.The recursion is initiated by setting R and X to be the empty set and P to be the vertex set of the graph. Within each recursive call, the algorithm considers the vertices in P in turn; if there are no such vertices, it either reports R as a maximal clique, or backtracks. For each vertex v chosen from P, it makes a recursive call in which v is added to R and in which P and X are restricted to the neighbor set N of v, which finds and reports all clique extensions of R that contain v. Then, it moves v from P to X to exclude it from consideration in future cliques and continues with the next vertex in P.
That is, in pseudocode, the algorithm performs the following steps:
algorithm BronKerbosch1 is
if P and X are both empty then
report R as a maximal clique
for each vertex v in P do
BronKerbosch1, X ⋂ N)
P := P \
X := X ⋃
With pivoting
The basic form of the algorithm, described above, is inefficient in the case of graphs with many non-maximal cliques: it makes a recursive call for every clique, maximal or not. To save time and allow the algorithm to backtrack more quickly in branches of the search that contain no maximal cliques, Bron and Kerbosch introduced a variant of the algorithm involving a "pivot vertex" u, chosen from P. Any maximal clique must include either u or one of its non-neighbors, for otherwise the clique could be augmented by adding u to it. Therefore, only u and its non-neighbors need to be tested as the choices for the vertex v that is added to R in each recursive call to the algorithm. In pseudocode:algorithm BronKerbosch2 is
if P and X are both empty then
report R as a maximal clique
choose a pivot vertex u in P ⋃ X
for each vertex v in P \ N do
BronKerbosch2, X ⋂ N)
P := P \
X := X ⋃
If the pivot is chosen to minimize the number of recursive calls made by the algorithm, the savings in running time compared to the non-pivoting version of the algorithm can be significant.
With vertex ordering
An alternative method for improving the basic form of the Bron–Kerbosch algorithm involves forgoing pivoting at the outermost level of recursion, and instead choosing the ordering of the recursive calls carefully in order to minimize the sizes of the sets of candidate vertices within each recursive call.The degeneracy of a graph is the smallest number such that every subgraph of has a vertex with degree or less. Every graph has a degeneracy ordering, an ordering of the vertices such that each vertex has or fewer neighbors that come later in the ordering; a degeneracy ordering may be found in linear time by repeatedly selecting the vertex of minimum degree among the remaining vertices. If the order of the vertices that the Bron–Kerbosch algorithm loops through is a degeneracy ordering, then the set of candidate vertices in each call will be guaranteed to have size at most . The set of excluded vertices will consist of all earlier neighbors of, and may be much larger than . In recursive calls to the algorithm below the topmost level of the recursion, the pivoting version can still be used.
In pseudocode, the algorithm performs the following steps:
algorithm BronKerbosch3 is
P = V
R = X = empty
for each vertex v in a degeneracy ordering of G do
BronKerbosch2, X ⋂ N)
P := P \
X := X ⋃
This variant of the algorithm can be proven to be efficient for graphs of small degeneracy, and experiments show that it also works well in practice for large sparse social networks and other real-world graphs.
Example
In the example graph shown, the algorithm is initially called with R = Ø, P = , and X = Ø. The pivot u should be chosen as one of the degree-three vertices, to minimize the number of recursive calls; for instance, suppose that u is chosen to be vertex 2. Then there are three remaining vertices in P \ N: vertices 2, 4, and 6.The iteration of the inner loop of the algorithm for v = 2 makes a recursive call to the algorithm with R = , P = , and X = Ø. Within this recursive call, one of 1 or 5 will be chosen as a pivot, and there will be two second-level recursive calls, one for vertex 3 and the other for whichever vertex was not chosen as pivot. These two calls will eventually report the two cliques and. After returning from these recursive calls, vertex 2 is added to X and removed from P.
The iteration of the inner loop of the algorithm for v = 4 makes a recursive call to the algorithm with R = , P = , and X = Ø. This recursive call will end up making three second-level recursive calls to the algorithm that report the three cliques,, and. Then, vertex 4 is added to X and removed from P.
In the third and final iteration of the inner loop of the algorithm, for v = 6, there is a recursive call to the algorithm with R = , P = Ø, and X = . Because this recursive call has P empty and X non-empty, it immediately backtracks without reporting any more cliques, as there can be no maximal clique that includes vertex 6 and excludes vertex 4.
The call tree for the algorithm, therefore, looks like:
BronKerbosch2
BronKerbosch2
BronKerbosch2: output
BronKerbosch2
BronKerbosch2: output
BronKerbosch2
BronKerbosch2: output
BronKerbosch2: output
BronKerbosch2: output
BronKerbosch2: no output
The graph in the example has degeneracy two; one possible degeneracy ordering is 6,4,3,1,2,5. If the vertex-ordering version of the Bron–Kerbosch algorithm is applied to the vertices, in this order, the call tree looks like
BronKerbosch3
BronKerbosch2
BronKerbosch2: output
BronKerbosch2
BronKerbosch2: output
BronKerbosch2: output
BronKerbosch2
BronKerbosch2: output
BronKerbosch2
BronKerbosch2
BronKerbosch2: output
BronKerbosch2: no output
BronKerbosch2: no output
Worst-case analysis
The Bron–Kerbosch algorithm is not an output-sensitive algorithm: unlike some other algorithms for the clique problem, it does not run in polynomial time per maximal clique generated. However, it is efficient in a worst-case sense: by a result of, any n-vertex graph has at most 3n/3 maximal cliques, and the worst-case running time of the Bron–Kerbosch algorithm is O, matching this bound.For sparse graphs, tighter bounds are possible. In particular the vertex-ordering version of the Bron–Kerbosch algorithm can be made to run in time, where is the degeneracy of the graph, a measure of its sparseness. There exist -degenerate graphs for which the total number of maximal cliques is, so this bound is close to tight.