function [nodes, kc] = knottycentrality(CIJ,compact)
% Attempts to find the sub-graph of CIJ with the highest value for
% knotty-centrality. Carries out a series of exhaustive searches on
% subsets of the nodes ranked by "indirect" betweenness centrality, then
% carries out a phase of hill-climbing to see whether the sub-graph can
% be improved by adding further nodes. Uses the Brain Connectivity
% Toolbox (Rubinov & Sporns, 2010) for betweenness centrality
%
% nodes = the sub-graph found
% kc = its knotty-centredness
% compact = 1 if compact knotty-centrality to be used, 0 otherwise
%
% Written by Murray Shanahan, October 2011
% REF: Shanahan M, Wildie M. Knotty-centrality: finding the connective core of a
% complex network. PLoS One. 2012;7(5):e36579. Epub 2012 May 9. PubMed PMID:
% 22590571; PubMed Central PMCID: PMC3348887.
N = length(CIJ);
CIJ = (CIJ > 0).*1; % binarise matrix - all non-zero weights become 1s
% Exhastive search phase
Exh = 10; % number of nodes for exhaustive search (2^Exh combinations)
Exh = min(Exh,N);
BC = betweenness_centrality(CIJ); % betweenness centralities (Rubinov & Sporns)
BC = BC/sum(BC); % normalise wrt total betweenness centrality
% Calculate indirect betweenness centrality
BC2 = zeros(1,N);
for i = 1:N
BC2(i) = BC(i)+(sum(CIJ(i,:).*BC(i)))+(sum(CIJ(:,i)'.*BC(i)));
end
[~, IxBC] = sort(BC2,'descend'); % rank nodes
nodes = [];
improving = 1;
while improving
L = length(nodes);
nodes_left = IxBC;
nodes_left = nodes_left(~ismember(nodes_left,nodes));
choices = nodes_left(1:min(Exh,end));
[nodes, kc] = BestPerm(nodes,choices,CIJ,compact,BC);
improving = length(nodes) > L;
end
% Hill climbing phase
nodes_left = 1:N;
nodes_left = nodes_left(~ismember(nodes_left,nodes));
improving = 1;
while improving && ~isempty(nodes_left)
best_kc = 0;
for i = 1:length(nodes_left)
node = nodes_left(i);
nodes2 = [nodes, node];
kc2 = KnottyCentrality(CIJ,nodes2,compact,BC);
if kc2 > best_kc
best_kc = kc2;
best_node = node;
end
end
if best_kc > kc
kc = best_kc;
nodes = [nodes, best_node];
nodes_left = nodes_left(nodes_left ~= best_node);
else
improving = 0;
end
end
end
function [nodes,kc] = BestPerm(given,choices,CIJ,compact,BC)
% Carries out exhaustive search to find a permutation of nodes in
% "choices" that when added to the nodes in "given" yields the highest
% value of knotty-centrality
if ~isempty(choices)
choices2 = choices(2:end);
new = choices(1);
[nodes1,kc1] = BestPerm([given, new],choices2,CIJ,compact,BC);
[nodes2,kc2] = BestPerm(given,choices2,CIJ,compact,BC);
if kc1 > kc2
nodes = nodes1;
kc = kc1;
else
nodes = nodes2;
kc = kc2;
end
else
nodes = given;
kc = KnottyCentrality(CIJ,nodes,compact,BC);
end
end
function kc = KnottyCentrality(CIJ,nodes,compact,BC)
% Returns knotty-centrality of the subgraph of CIJ comprising only
% "nodes" and the associated connections
if length(nodes) < 3
kc = 0;
else
CIJ = (CIJ > 0).*1; % binarise matrix
N = length(CIJ); % nodes in overall graph
M = length(nodes); % nodes in subgraph
BCtot = sum(BC(nodes));
p = ((N-M)/N); % proportion of nodes not in subgraph
RC = sum(sum(CIJ(nodes,nodes)))/(M*(M-1)); % density of subgraph
if compact
kc = p*BCtot*RC; % compact knotty-centrality
else
kc = BCtot*RC; % knotty-centrality
end
end
end