I have implemented both versions specified in the paper. I learned that, the unoptimized version, if solved recursively helps a lot to understand the algorithm.
Here is python implementation for version 1 (unoptimized):
def bron(compsub, _not, candidates, graph, cliques):
if len(candidates) == 0 and len(_not) == 0:
cliques.append(tuple(compsub))
return
if len(candidates) == 0: return
sel = candidates[0]
candidates.remove(sel)
newCandidates = removeDisconnected(candidates, sel, graph)
newNot = removeDisconnected(_not, sel, graph)
compsub.append(sel)
bron(compsub, newNot, newCandidates, graph, cliques)
compsub.remove(sel)
_not.append(sel)
bron(compsub, _not, candidates, graph, cliques)
And you invoke this function:
graph = # 2x2 boolean matrix
cliques = []
bron([], [], graph, cliques)
The variable cliques
will contain cliques found.
Once you understand this it's easy to implement optimized one.
X
is not empty andP
is empty it means that we find one sub-clique instead of one maximal clique. – Tasha