-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathrandom_graph.m
97 lines (80 loc) · 3.52 KB
/
random_graph.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
% Random graph construction routine with various models
% INPUTS: N - number of nodes
% p - probability, 0<=p<=1, for all other inputs, p is not considered
% E - fixed number of edges
% distribution - probability distribution: use the "connecting-stubs model" generation model
% degrees - particular degree sequence, used only if distribution = 'sequence'
% OUTPUTS: adj - adjacency matrix of generated graph (symmetric)
% Note 1: Default is Erdos-Renyi graph G(n,0.5)
% Note 2: Generates undirected, simple graphs only
% Note 3: In the worst-case scenario for a given degree distribution, the algorithm is very slow, and it works by restarting itself.
% Source: Various random graph models from the literature
% Other routines: numedges.m, isgraphic.m
% GB, October 31, 2005
function adj = random_graph(n,p,E,distribution,degrees)
adj=zeros(n); % initialize adjacency matrix
switch nargin
case 1 % just the number of nodes, n
% 0.5 - default probability of attachment
for i=1:n
for j=i+1:n
if rand<=0.5; adj(i,j)=1; adj(j,i)=1; end
end
end
case 2 % the number of nodes and the probability of attachment, n, p
for i=1:n
for j=i+1:n
if rand<=p; adj(i,j)=1; adj(j,i)=1; end
end
end
case 3 % fixed number of nodes and edges, n, E
while numedges(adj) < E
i=randi(n); j=randi(n);
if i==j | adj(i,j)>0; continue; end % do not allow self-loops or double edges
adj(i,j)=adj(i,j)+1; adj(j,i)=adj(i,j);
end
otherwise % pick from a distribution; generate *n* random numbers from a distribution
Nseq=1; % ensure the while loops start
switch distribution
case 'uniform'
while not(isgraphic(Nseq)) % make sure Nseq is a graphic sequence
Nseq = randi(n-1,1,n);
end
case 'normal'
while not(isgraphic(Nseq)) % make sure Nseq is a graphic sequence
Nseq = ceil((n-1)/10*randn(1,n)+(n-1)/2);
end
case 'binomial'
p=0.5; % default parameter for binomial distribution
while not(isgraphic(Nseq)) % make sure Nseq is a graphic sequence
Nseq = ceil(binornd(n-1,p,1,n));
end
case 'exponential'
while not(isgraphic(Nseq)) % make sure Nseq is a graphic sequence
Nseq = ceil(exprnd((n-1)/4,1,n));
end
case 'sequence'
if nargin<5; fprintf('for distribution="sequence", need to specify a custom degree sequence\n'); return; end
if not(isgraphic(degrees)); fprintf('degrees is not a graphic sequence - select a different sequence\n'); return; end
Nseq = degrees;
end
% connect stubs at random
stubs=Nseq;
old_sum = 0;
cnt=0;
while sum(stubs)>0 % while no more stubs are left to connect
new_sum = sum(stubs);
if old_sum==new_sum; cnt = cnt+1; end
if old_sum~=new_sum; cnt=0; end
if cnt>100; stubs = Nseq; adj=zeros(length(Nseq)); cnt=0; end
old_sum = sum(stubs);
[~,n1] = max(stubs);
ind = find(stubs>0);
n2 = ind(randi(length(ind)));
if n1==n2; continue; end
if adj(n1,n2)>0; continue; end
adj(n1,n2)=1; adj(n2,n1)=1;
stubs(n1) = stubs(n1) - 1;
stubs(n2) = stubs(n2) - 1;
end
end % end nargin options