1
2
3
4
5
6
7
8
9
10 package edu.uci.ics.jung.algorithms.generators.random;
11
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Random;
19 import java.util.Set;
20
21 import com.google.common.base.Preconditions;
22 import com.google.common.base.Supplier;
23
24 import edu.uci.ics.jung.algorithms.generators.EvolvingGraphGenerator;
25 import edu.uci.ics.jung.algorithms.util.WeightedChoice;
26 import edu.uci.ics.jung.graph.Graph;
27 import edu.uci.ics.jung.graph.MultiGraph;
28 import edu.uci.ics.jung.graph.util.EdgeType;
29 import edu.uci.ics.jung.graph.util.Pair;
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 public class BarabasiAlbertGenerator<V, E> implements EvolvingGraphGenerator<V, E> {
84 private Graph<V, E> mGraph = null;
85 private int mNumEdgesToAttachPerStep;
86 private int mElapsedTimeSteps;
87 private Random mRandom;
88 protected List<V> vertex_index;
89 protected int init_vertices;
90 protected Map<V, Integer> index_vertex;
91 protected Supplier<Graph<V, E>> graphFactory;
92 protected Supplier<V> vertexFactory;
93 protected Supplier<E> edgeFactory;
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 public BarabasiAlbertGenerator(Supplier<Graph<V, E>> graphFactory, Supplier<V> vertexFactory,
118 Supplier<E> edgeFactory, int init_vertices, int numEdgesToAttach, int seed, Set<V> seedVertices) {
119 Preconditions.checkArgument(init_vertices > 0,
120 "Number of initial unconnected 'seed' vertices must be positive");
121 Preconditions.checkArgument(numEdgesToAttach > 0,
122 "Number of edges to attach at each time step must be positive");
123 Preconditions.checkArgument(numEdgesToAttach <= init_vertices,
124 "Number of edges to attach at each time step must less than or equal to the number of initial vertices");
125
126 mNumEdgesToAttachPerStep = numEdgesToAttach;
127 mRandom = new Random(seed);
128 this.graphFactory = graphFactory;
129 this.vertexFactory = vertexFactory;
130 this.edgeFactory = edgeFactory;
131 this.init_vertices = init_vertices;
132 initialize(seedVertices);
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154 public BarabasiAlbertGenerator(Supplier<Graph<V, E>> graphFactory, Supplier<V> vertexFactory,
155 Supplier<E> edgeFactory, int init_vertices, int numEdgesToAttach, Set<V> seedVertices) {
156 this(graphFactory, vertexFactory, edgeFactory, init_vertices, numEdgesToAttach,
157 (int) System.currentTimeMillis(), seedVertices);
158 }
159
160 private void initialize(Set<V> seedVertices) {
161 mGraph = graphFactory.get();
162
163 vertex_index = new ArrayList<V>(2 * init_vertices);
164 index_vertex = new HashMap<V, Integer>(2 * init_vertices);
165 for (int i = 0; i < init_vertices; i++) {
166 V v = vertexFactory.get();
167 mGraph.addVertex(v);
168 vertex_index.add(v);
169 index_vertex.put(v, i);
170 seedVertices.add(v);
171 }
172
173 mElapsedTimeSteps = 0;
174 }
175
176 public void evolveGraph(int numTimeSteps) {
177
178 for (int i = 0; i < numTimeSteps; i++) {
179 evolveGraph();
180 mElapsedTimeSteps++;
181 }
182 }
183
184 private void evolveGraph() {
185 Collection<V> preexistingNodes = mGraph.getVertices();
186 V newVertex = vertexFactory.get();
187
188 mGraph.addVertex(newVertex);
189
190
191
192
193 Set<Pair<V>> added_pairs = createRandomEdges(preexistingNodes, newVertex, mNumEdgesToAttachPerStep);
194
195 for (Pair<V> pair : added_pairs) {
196 V v1 = pair.getFirst();
197 V v2 = pair.getSecond();
198 if (mGraph.getDefaultEdgeType() != EdgeType.UNDIRECTED || !mGraph.isNeighbor(v1, v2))
199 mGraph.addEdge(edgeFactory.get(), pair);
200 }
201
202
203 vertex_index.add(newVertex);
204 index_vertex.put(newVertex, new Integer(vertex_index.size() - 1));
205 }
206
207 private Set<Pair<V>> createRandomEdges(Collection<V> preexistingNodes, V newVertex, int numEdges) {
208 Set<Pair<V>> added_pairs = new HashSet<Pair<V>>(numEdges * 3);
209
210
211 Map<V, Double> item_weights = new HashMap<V, Double>();
212 for (V v : preexistingNodes) {
213
214
215
216
217
218 if (v == newVertex)
219 continue;
220
221 double degree;
222 double denominator;
223
224
225
226
227
228
229
230
231
232 if (mGraph.getDefaultEdgeType() == EdgeType.UNDIRECTED) {
233 degree = mGraph.degree(v);
234 denominator = (2 * mGraph.getEdgeCount()) + mGraph.getVertexCount() - 1;
235 } else {
236 degree = mGraph.inDegree(v);
237 denominator = mGraph.getEdgeCount() + mGraph.getVertexCount() - 1;
238 }
239
240 double prob = (degree + 1) / denominator;
241 item_weights.put(v, prob);
242 }
243 WeightedChoice<V> nodeProbabilities = new WeightedChoice<V>(item_weights, mRandom);
244
245 for (int i = 0; i < numEdges; i++) {
246 createRandomEdge(preexistingNodes, newVertex, added_pairs, nodeProbabilities);
247 }
248
249 return added_pairs;
250 }
251
252 private void createRandomEdge(Collection<V> preexistingNodes, V newVertex, Set<Pair<V>> added_pairs,
253 WeightedChoice<V> weightedProbabilities) {
254 V attach_point;
255 boolean created_edge = false;
256 Pair<V> endpoints;
257
258 do {
259 attach_point = weightedProbabilities.nextItem();
260
261 endpoints = new Pair<V>(newVertex, attach_point);
262
263
264
265
266
267
268
269 if (!(mGraph instanceof MultiGraph)) {
270 if (added_pairs.contains(endpoints))
271 continue;
272 if (mGraph.getDefaultEdgeType() == EdgeType.UNDIRECTED
273 && added_pairs.contains(new Pair<V>(attach_point, newVertex)))
274 continue;
275 }
276 created_edge = true;
277 } while (!created_edge);
278
279 added_pairs.add(endpoints);
280
281 if (mGraph.getDefaultEdgeType() == EdgeType.UNDIRECTED) {
282 added_pairs.add(new Pair<V>(attach_point, newVertex));
283 }
284 }
285
286 public int numIterations() {
287 return mElapsedTimeSteps;
288 }
289
290 public Graph<V, E> get() {
291 return mGraph;
292 }
293 }