-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmaximalCliques.m
executable file
·133 lines (111 loc) · 4.85 KB
/
maximalCliques.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
function [ MC ] = maximalCliques( A, v_str )
%MAXIMALCLIQUES Find maximal cliques using the Bron-Kerbosch algorithm
% Given a graph's boolean adjacency matrix, A, find all maximal cliques
% on A using the Bron-Kerbosch algorithm in a recursive manner. The
% graph is required to be undirected and must contain no self-edges.
%
% V_STR is an optional input string with the version of the Bron-Kerbosch
% algorithm to be used (either 'v1' or 'v2'). Version 2 is faster (and
% default), and version 1 is included for posterity.
%
% MC is the output matrix that contains the maximal cliques in its
% columns.
%
% Note: This function can be used to compute the maximal independent sets
% of a graph A by providing the complement of A as the input graph.
%
% Note: This function can be used to compute the maximal matchings of a
% graph A by providing the complement of the line graph of A as the input
% graph.
%
% Ref: Bron, Coen and Kerbosch, Joep, "Algorithm 457: finding all cliques
% of an undirected graph", Communications of the ACM, vol. 16, no. 9,
% pp: 575–577, September 1973.
%
% Ref: Cazals, F. and Karande, C., "A note on the problem of reporting
% maximal cliques", Theoretical Computer Science (Elsevier), vol. 407,
% no. 1-3, pp: 564-568, November 2008.
%
% Jeffrey Wildman (c) 2011
%
% Updated: 10/27/2011 - updated documentation & removal of ~ punctuation
% to ignore function output arguments for better compatibility with older
% MATLAB versions prior to 2009b (Thanks to Akli Benali).
% first, some input checking
if size(A,1) ~= size(A,2)
error('MATLAB:maximalCliques', 'Adjacency matrix is not square.');
elseif ~all(all((A==1) | (A==0)))
error('MATLAB:maximalCliques', 'Adjacency matrix is not boolean (zero-one valued).')
elseif ~all(all(A==A.'))
error('MATLAB:maximalCliques', 'Adjacency matrix is not undirected (symmetric).')
elseif trace(abs(A)) ~= 0
error('MATLAB:maximalCliques', 'Adjacency matrix contains self-edges (check your diagonal).');
end
if ~exist('v_str','var')
v_str = 'v2';
end
if ~strcmp(v_str,'v1') && ~strcmp(v_str,'v2')
warning('MATLAB:maximalCliques', 'Version not recognized, defaulting to v2.');
v_str = 'v2';
end
% second, set up some variables
n = size(A,2); % number of vertices
MC = []; % storage for maximal cliques
R = []; % currently growing clique
P = 1:n; % prospective nodes connected to all nodes in R
X = []; % nodes already processed
% third, run the algorithm!
if strcmp(v_str,'v1')
BKv1(R,P,X);
else
BKv2(R,P,X);
end
% version 1 of the Bron-Kerbosch algo
function [] = BKv1 ( R, P, X )
if isempty(P) && isempty(X)
% report R as a maximal clique
newMC = zeros(1,n);
newMC(R) = 1; % newMC contains ones at indices equal to the values in R
MC = [MC newMC.'];
else
for u = P
P = setxor(P,u);
Rnew = [R u];
Nu = find(A(u,:));
Pnew = intersect(P,Nu);
Xnew = intersect(X,Nu);
BKv1(Rnew, Pnew, Xnew);
X = [X u];
end
end
end % BKv1
% version 2 of the Bron-Kerbosch algo
function [] = BKv2 ( R, P, X )
ignore = []; % less elegant ignore function output variable, but works with older versions of MATLAB: <2009b
if (isempty(P) && isempty(X))
% report R as a maximal clique
newMC = zeros(1,n);
newMC(R) = 1; % newMC contains ones at indices equal to the values in R
MC = [MC newMC.'];
else
% choose pivot
ppivots = union(P,X); % potential pivots
binP = zeros(1,n);
binP(P) = 1; % binP contains ones at indices equal to the values in P
% rows of A(ppivots,:) contain ones at the neighbors of ppivots
pcounts = A(ppivots,:)*binP.'; % cardinalities of the sets of neighbors of each ppivots intersected with P
[ignore,ind] = max(pcounts);
u_p = ppivots(ind); % select one of the ppivots with the largest count
for u = intersect(find(~A(u_p,:)),P) % all prospective nodes who are not neighbors of the pivot
P = setxor(P,u);
Rnew = [R u];
Nu = find(A(u,:));
Pnew = intersect(P,Nu);
Xnew = intersect(X,Nu);
BKv2(Rnew, Pnew, Xnew);
X = [X u];
end
end
end % BKv2
end % maximalCliques