FormationControlSimulation/SOURCE/networks-toolbox/buildSmaxGraph.m

169 lines
4.7 KiB
Matlab

% Construct the graph with the maximum possible s-metric, given the degree
% sequence; the s-metric is the sum of products of degrees across all edges
% Source: Li et al "Towards a Theory of Scale-Free Graphs"
%
% INPUTs: degree sequence: 1xn vector of positive integers (graphic)
% OUTPUTs: edge list of the s-max graph, mx3
%
% GB: last updated, November 9 2012
function gA=buildSmaxGraph(deg)
didj=[];
for ii=1:length(deg)-1
for jj=ii+1:length(deg)
% [deg_i*deg_j, 'B', deg_i, deg_j, 'B', i, j] - 'B' for sorting purposes
didj=[didj; deg(ii)*deg(jj), 2, deg(ii), deg(jj), 2, ii,jj];
end
end
didj=sortrows(didj);
didj=didj(end:-1:1,:); % reverse to decreasing order
w=deg; % number of remaining stubs - originally equals the degrees
[~,maxdegind]=max(deg); % the index of the maximum degree
A=[maxdegind];
B = setdiff([1:length(deg)],maxdegind);
wA=deg(maxdegind); % remaining stubs in A
dB=sum(deg(B)); % total degree of unattached vertices in B
gA=[]; % initialize empty edge list
while sum(w)>0 % while there are still stubs to connect
% STEP 1 (LINK SELECTION)
if size(didj,1)==0
if sum(w)>0 % connect all stubs left
wstubs=[];
cnt=1;
for ww=1:length(w)
while w(ww)>0
wstubs=[wstubs; cnt, ww];
w(ww)=w(ww)-1;
cnt=cnt+1;
end
end
for xx=1:size(wstubs,1)/2
n1=wstubs(xx,2);
n2=wstubs(xx+size(wstubs,1)/2,2);
ind1=find(gA(:,1)==n1);
if length(ind1)==0
first_case=false;
else
ind2=find(gA(ind1,2)==n2);
if length(ind2)==0
first_case=false;
else
first_case=true;
end
end
ind2=find(gA(:,1)==n2);
if length(ind2)==0
second_case=false;
else
ind1=find(gA(ind2,2)==n1);
if length(ind1)==0
second_case=false;
else
second_case=true;
end
end
if first_case %if [n1,n2,1] in gA and not(n1==n2):
gA=[gA; n1,n2,1];
elseif second_case % if [n2,n1,1] in gA and not(n1==n2):
gA=[gA; n2,n1,1];
elseif n1==n2
gA=[gA; n1,n2,1];
end
end
end
return % gA
end
% eliminate zero stubs in didj
didj_new=[];
for ii=1:size(didj,1)
if w(didj(ii,6))>0 && w(didj(ii,7))>0
didj_new=[didj_new; didj(ii,:)];
end
end
didj=didj_new;
clear didj_new
if size(didj,1)==0; continue; end
for ii=1:size(didj,1)
edge=[didj(ii,6), didj(ii,7)];
if length(find(A==edge(1)))>0 && length(find(A==edge(2)))>0
didj(ii,:)=[didj(ii,1),100,w(edge(1)),w(edge(2)),100,edge(1),edge(2)];
elseif length(find(A==edge(1)))>0 && length(find(B==edge(2)))>0
didj(ii,:)=[didj(ii,1),100,w(edge(1)),w(edge(2)),2,edge(1),edge(2)];
elseif length(find(B==edge(1)))>0 && length(find(A==edge(2)))>0
didj(ii,:)=[didj(ii,1),2,w(edge(1)),w(edge(2)),1,edge(1),edge(2)];
didj(ii,:)=[didj(ii,1),100,w(edge(2)),w(edge(1)),2,edge(2),edge(1)];
else
didj(ii,:)=[didj(ii,1),2,w(edge(1)),w(edge(2)),2,edge(1),edge(2)];
end
end
didj=sortrows(didj);
didj=didj(end:-1:1,:);
link_select=[didj(1,6),didj(1,7)]; % select the first link that starts in A
% STEP 2 (LINK ADDITION)
n1=link_select(1);
n2=link_select(2);
% if (n1 in A and n2 in B) or (n1 in B and n2 in A)
if (length(find(A==n1))>0 && length(find(B==n2))>0) || (length(find(B==n1))>0 && length(find(A==n2))>0)
gA=[gA; n1, n2, 1];
if length(find(A==n1))>0 && length(find(B==n2))>0
B = setdiff(B,n2);
A=[A; n2];
end
if length(find(B==n1))>0 && length(find(A==n2))>0
B = setdiff(B,n1);
A=[A; n1];
end
w(n1)=w(n1)-1;
w(n2)=w(n2)-1;
wA=sum(w(A));
dB=sum(deg(B));
didj=didj(2:size(didj,1),:); % remove link from top
elseif length(find(A==n1))>0 && length(find(A==n2))>0
% check the tree condition
if dB==2*length(B)-wA
didj=didj(2:size(didj,1),:);
elseif wA==2 && length(B)>0 % results in a disconnected graph
didj=didj(2:size(didj,1),:);
else % add it!
gA=[gA; n1,n2,1];
w(n1)=w(n1)-1;
w(n2)=w(n2)-1;
wA=sum(w(A));
dB=sum(deg(B));
didj=didj(2:size(didj,1),:);
end
end
end