Я реализовал обе версии, указанные в статье. Я узнал, что неоптимизированная версия, если ее решить рекурсивно, очень помогает понять алгоритм.
Вот реализация Python для версии 1 (неоптимизированная):
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)
И вы вызываете эту функцию:
graph = # 2x2 boolean matrix
cliques = []
bron([], [], graph, cliques)
Переменная cliques
будет содержать найденные клики.
Как только вы поймете это, вы легко сможете реализовать оптимизированный.