Switch to unified view

a b/graph_algorithm/GraphGenerator.java
1
package GraphAlgorithm;
2
3
import java.util.HashSet;
4
import java.util.Set;
5
6
import org.apache.commons.math3.distribution.BinomialDistribution;
7
import org.apache.commons.math3.distribution.UniformIntegerDistribution;
8
9
import network.DisGraph;
10
import util.StdRandom;
11
12
/******************************************************************************
13
 *  Compilation:  javac GraphGenerator.java
14
 *  Execution:    java GraphGenerator V E
15
 *  Dependencies: Graph.java
16
 *
17
 *  A graph generator.
18
 *
19
 *  For many more graph generators, see
20
 *  http://networkx.github.io/documentation/latest/reference/generators.html
21
 *
22
 ******************************************************************************/
23
24
/**
25
 *  The {@code GraphGenerator} class provides static methods for creating
26
 *  various graphs, including Erdos-Renyi random graphs, random bipartite
27
 *  graphs, random k-regular graphs, and random rooted trees.
28
 *  <p>
29
 *  For additional documentation, see <a href="https://algs4.cs.princeton.edu/41graph">Section 4.1</a> of
30
 *  <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
31
 *
32
 *  @author Robert Sedgewick
33
 *  @author Kevin Wayne
34
 */
35
public class GraphGenerator {
36
    private static final class Edge implements Comparable<Edge> {
37
        private int v;
38
        private int w;
39
40
        private Edge(int v, int w) {
41
            if (v < w) {
42
                this.v = v;
43
                this.w = w;
44
            }
45
            else {
46
                this.v = w;
47
                this.w = v;
48
            }
49
        }
50
51
        public int compareTo(Edge that) {
52
            if (this.v < that.v) return -1;
53
            if (this.v > that.v) return +1;
54
            if (this.w < that.w) return -1;
55
            if (this.w > that.w) return +1;
56
            return 0;
57
        }
58
    }
59
60
    // this class cannot be instantiated
61
    private GraphGenerator() { }
62
63
    /**
64
     * Returns a random simple graph containing {@code V} vertices and {@code E} edges.
65
     * @param V the number of vertices
66
     * @param E the number of vertices
67
     * @return a random simple graph on {@code V} vertices, containing a total
68
     *     of {@code E} edges
69
     * @throws IllegalArgumentException if no such simple graph exists
70
     */
71
    public static DisGraph simple(int V, int E) {
72
        if (E > (long) V*(V-1)/2) throw new IllegalArgumentException("Too many edges");
73
        if (E < 0)                throw new IllegalArgumentException("Too few edges");
74
        DisGraph G = new DisGraph(V);
75
        Set<Edge> set = new HashSet<Edge>();
76
        while (G.getEdges() < E) {
77
            int v = StdRandom.uniform(V);
78
            int w = StdRandom.uniform(V);
79
            Edge e = new Edge(v, w);
80
            if ((v != w) && !set.contains(e)) {
81
                set.add(e);
82
                G.addEdge(v, w);
83
            }
84
        }
85
        return G;
86
    }
87
88
    /**
89
     * Returns a random simple graph on {@code V} vertices, with an 
90
     * edge between any two vertices with probability {@code p}. This is sometimes
91
     * referred to as the Erdos-Renyi random graph model.
92
     * @param V the number of vertices
93
     * @param p the probability of choosing an edge
94
     * @return a random simple graph on {@code V} vertices, with an edge between
95
     *     any two vertices with probability {@code p}
96
     * @throws IllegalArgumentException if probability is not between 0 and 1
97
     */
98
    public static DisGraph simple(int V, double p) {
99
        if (p < 0.0 || p > 1.0)
100
            throw new IllegalArgumentException("Probability must be between 0 and 1");
101
        DisGraph G = new DisGraph(V);
102
        for (int v = 0; v < V; v++)
103
            for (int w = v+1; w < V; w++)
104
                if (StdRandom.bernoulli(p))
105
                    G.addEdge(v, w);
106
        return G;
107
    }
108
109
    /**
110
     * Returns the complete graph on {@code V} vertices.
111
     * @param V the number of vertices
112
     * @return the complete graph on {@code V} vertices
113
     */
114
    public static DisGraph complete(int V) {
115
        return simple(V, 1.0);
116
    }
117
118
    /**
119
     * Returns a complete bipartite graph on {@code V1} and {@code V2} vertices.
120
     * @param V1 the number of vertices in one partition
121
     * @param V2 the number of vertices in the other partition
122
     * @return a complete bipartite graph on {@code V1} and {@code V2} vertices
123
     * @throws IllegalArgumentException if probability is not between 0 and 1
124
     */
125
//    public static DisGraph completeBipartite(int V1, int V2) {
126
//        return bipartite(V1, V2, V1*V2);
127
//    }
128
129
    /**
130
     * Returns a random simple bipartite graph on {@code V1} and {@code V2} vertices
131
     * with {@code E} edges.
132
     * @param V1 the number of vertices in one partition
133
     * @param V2 the number of vertices in the other partition
134
     * @param E the number of edges
135
     * @return a random simple bipartite graph on {@code V1} and {@code V2} vertices,
136
     *    containing a total of {@code E} edges
137
     * @throws IllegalArgumentException if no such simple bipartite graph exists
138
     */
139
//    public static DisGraph bipartite(int V1, int V2, int E) {
140
//        if (E > (long) V1*V2) throw new IllegalArgumentException("Too many edges");
141
//        if (E < 0)            throw new IllegalArgumentException("Too few edges");
142
//        DisGraph G = new Graph(V1 + V2);
143
//
144
//        int[] vertices = new int[V1 + V2];
145
//        for (int i = 0; i < V1 + V2; i++)
146
//            vertices[i] = i;
147
//        StdRandom.shuffle(vertices);
148
//
149
//        SET<Edge> set = new SET<Edge>();
150
//        while (G.E() < E) {
151
//            int i = StdRandom.uniform(V1);
152
//            int j = V1 + StdRandom.uniform(V2);
153
//            Edge e = new Edge(vertices[i], vertices[j]);
154
//            if (!set.contains(e)) {
155
//                set.add(e);
156
//                G.addEdge(vertices[i], vertices[j]);
157
//            }
158
//        }
159
//        return G;
160
//    }
161
//
162
//    /**
163
//     * Returns a random simple bipartite graph on {@code V1} and {@code V2} vertices,
164
//     * containing each possible edge with probability {@code p}.
165
//     * @param V1 the number of vertices in one partition
166
//     * @param V2 the number of vertices in the other partition
167
//     * @param p the probability that the graph contains an edge with one endpoint in either side
168
//     * @return a random simple bipartite graph on {@code V1} and {@code V2} vertices,
169
//     *    containing each possible edge with probability {@code p}
170
//     * @throws IllegalArgumentException if probability is not between 0 and 1
171
//     */
172
//    public static Graph bipartite(int V1, int V2, double p) {
173
//        if (p < 0.0 || p > 1.0)
174
//            throw new IllegalArgumentException("Probability must be between 0 and 1");
175
//        int[] vertices = new int[V1 + V2];
176
//        for (int i = 0; i < V1 + V2; i++)
177
//            vertices[i] = i;
178
//        StdRandom.shuffle(vertices);
179
//        Graph G = new Graph(V1 + V2);
180
//        for (int i = 0; i < V1; i++)
181
//            for (int j = 0; j < V2; j++)
182
//                if (StdRandom.bernoulli(p))
183
//                    G.addEdge(vertices[i], vertices[V1+j]);
184
//        return G;
185
//    }
186
//
187
//    /**
188
//     * Returns a path graph on {@code V} vertices.
189
//     * @param V the number of vertices in the path
190
//     * @return a path graph on {@code V} vertices
191
//     */
192
//    public static Graph path(int V) {
193
//        Graph G = new Graph(V);
194
//        int[] vertices = new int[V];
195
//        for (int i = 0; i < V; i++)
196
//            vertices[i] = i;
197
//        StdRandom.shuffle(vertices);
198
//        for (int i = 0; i < V-1; i++) {
199
//            G.addEdge(vertices[i], vertices[i+1]);
200
//        }
201
//        return G;
202
//    }
203
//
204
//    /**
205
//     * Returns a complete binary tree graph on {@code V} vertices.
206
//     * @param V the number of vertices in the binary tree
207
//     * @return a complete binary tree graph on {@code V} vertices
208
//     */
209
//    public static Graph binaryTree(int V) {
210
//        Graph G = new Graph(V);
211
//        int[] vertices = new int[V];
212
//        for (int i = 0; i < V; i++)
213
//            vertices[i] = i;
214
//        StdRandom.shuffle(vertices);
215
//        for (int i = 1; i < V; i++) {
216
//            G.addEdge(vertices[i], vertices[(i-1)/2]);
217
//        }
218
//        return G;
219
//    }
220
//
221
//    /**
222
//     * Returns a cycle graph on {@code V} vertices.
223
//     * @param V the number of vertices in the cycle
224
//     * @return a cycle graph on {@code V} vertices
225
//     */
226
//    public static Graph cycle(int V) {
227
//        Graph G = new Graph(V);
228
//        int[] vertices = new int[V];
229
//        for (int i = 0; i < V; i++)
230
//            vertices[i] = i;
231
//        StdRandom.shuffle(vertices);
232
//        for (int i = 0; i < V-1; i++) {
233
//            G.addEdge(vertices[i], vertices[i+1]);
234
//        }
235
//        G.addEdge(vertices[V-1], vertices[0]);
236
//        return G;
237
//    }
238
//
239
//    /**
240
//     * Returns an Eulerian cycle graph on {@code V} vertices.
241
//     *
242
//     * @param  V the number of vertices in the cycle
243
//     * @param  E the number of edges in the cycle
244
//     * @return a graph that is an Eulerian cycle on {@code V} vertices
245
//     *         and {@code E} edges
246
//     * @throws IllegalArgumentException if either {@code V <= 0} or {@code E <= 0}
247
//     */
248
//    public static Graph eulerianCycle(int V, int E) {
249
//        if (E <= 0)
250
//            throw new IllegalArgumentException("An Eulerian cycle must have at least one edge");
251
//        if (V <= 0)
252
//            throw new IllegalArgumentException("An Eulerian cycle must have at least one vertex");
253
//        Graph G = new Graph(V);
254
//        int[] vertices = new int[E];
255
//        for (int i = 0; i < E; i++)
256
//            vertices[i] = StdRandom.uniform(V);
257
//        for (int i = 0; i < E-1; i++) {
258
//            G.addEdge(vertices[i], vertices[i+1]);
259
//        }
260
//        G.addEdge(vertices[E-1], vertices[0]);
261
//        return G;
262
//    }
263
//
264
//    /**
265
//     * Returns an Eulerian path graph on {@code V} vertices.
266
//     *
267
//     * @param  V the number of vertices in the path
268
//     * @param  E the number of edges in the path
269
//     * @return a graph that is an Eulerian path on {@code V} vertices
270
//     *         and {@code E} edges
271
//     * @throws IllegalArgumentException if either {@code V <= 0} or {@code E < 0}
272
//     */
273
//    public static Graph eulerianPath(int V, int E) {
274
//        if (E < 0)
275
//            throw new IllegalArgumentException("negative number of edges");
276
//        if (V <= 0)
277
//            throw new IllegalArgumentException("An Eulerian path must have at least one vertex");
278
//        Graph G = new Graph(V);
279
//        int[] vertices = new int[E+1];
280
//        for (int i = 0; i < E+1; i++)
281
//            vertices[i] = StdRandom.uniform(V);
282
//        for (int i = 0; i < E; i++) {
283
//            G.addEdge(vertices[i], vertices[i+1]);
284
//        }
285
//        return G;
286
//    }
287
//
288
//    /**
289
//     * Returns a wheel graph on {@code V} vertices.
290
//     * @param V the number of vertices in the wheel
291
//     * @return a wheel graph on {@code V} vertices: a single vertex connected to
292
//     *     every vertex in a cycle on {@code V-1} vertices
293
//     */
294
//    public static Graph wheel(int V) {
295
//        if (V <= 1) throw new IllegalArgumentException("Number of vertices must be at least 2");
296
//        Graph G = new Graph(V);
297
//        int[] vertices = new int[V];
298
//        for (int i = 0; i < V; i++)
299
//            vertices[i] = i;
300
//        StdRandom.shuffle(vertices);
301
//
302
//        // simple cycle on V-1 vertices
303
//        for (int i = 1; i < V-1; i++) {
304
//            G.addEdge(vertices[i], vertices[i+1]);
305
//        }
306
//        G.addEdge(vertices[V-1], vertices[1]);
307
//
308
//        // connect vertices[0] to every vertex on cycle
309
//        for (int i = 1; i < V; i++) {
310
//            G.addEdge(vertices[0], vertices[i]);
311
//        }
312
//
313
//        return G;
314
//    }
315
//
316
//    /**
317
//     * Returns a star graph on {@code V} vertices.
318
//     * @param V the number of vertices in the star
319
//     * @return a star graph on {@code V} vertices: a single vertex connected to
320
//     *     every other vertex
321
//     */
322
//    public static Graph star(int V) {
323
//        if (V <= 0) throw new IllegalArgumentException("Number of vertices must be at least 1");
324
//        Graph G = new Graph(V);
325
//        int[] vertices = new int[V];
326
//        for (int i = 0; i < V; i++)
327
//            vertices[i] = i;
328
//        StdRandom.shuffle(vertices);
329
//
330
//        // connect vertices[0] to every other vertex
331
//        for (int i = 1; i < V; i++) {
332
//            G.addEdge(vertices[0], vertices[i]);
333
//        }
334
//
335
//        return G;
336
//    }
337
//
338
//    /**
339
//     * Returns a uniformly random {@code k}-regular graph on {@code V} vertices
340
//     * (not necessarily simple). The graph is simple with probability only about e^(-k^2/4),
341
//     * which is tiny when k = 14.
342
//     *
343
//     * @param V the number of vertices in the graph
344
//     * @param k degree of each vertex
345
//     * @return a uniformly random {@code k}-regular graph on {@code V} vertices.
346
//     */
347
//    public static Graph regular(int V, int k) {
348
//        if (V*k % 2 != 0) throw new IllegalArgumentException("Number of vertices * k must be even");
349
//        Graph G = new Graph(V);
350
//
351
//        // create k copies of each vertex
352
//        int[] vertices = new int[V*k];
353
//        for (int v = 0; v < V; v++) {
354
//            for (int j = 0; j < k; j++) {
355
//                vertices[v + V*j] = v;
356
//            }
357
//        }
358
//
359
//        // pick a random perfect matching
360
//        StdRandom.shuffle(vertices);
361
//        for (int i = 0; i < V*k/2; i++) {
362
//            G.addEdge(vertices[2*i], vertices[2*i + 1]);
363
//        }
364
//        return G;
365
//    }
366
//
367
//    // http://www.proofwiki.org/wiki/Labeled_Tree_from_Prüfer_Sequence
368
//    // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.36.6484&rep=rep1&type=pdf
369
//    /**
370
//     * Returns a uniformly random tree on {@code V} vertices.
371
//     * This algorithm uses a Prufer sequence and takes time proportional to <em>V log V</em>.
372
//     * @param V the number of vertices in the tree
373
//     * @return a uniformly random tree on {@code V} vertices
374
//     */
375
//    public static Graph tree(int V) {
376
//        Graph G = new Graph(V);
377
//
378
//        // special case
379
//        if (V == 1) return G;
380
//
381
//        // Cayley's theorem: there are V^(V-2) labeled trees on V vertices
382
//        // Prufer sequence: sequence of V-2 values between 0 and V-1
383
//        // Prufer's proof of Cayley's theorem: Prufer sequences are in 1-1
384
//        // with labeled trees on V vertices
385
//        int[] prufer = new int[V-2];
386
//        for (int i = 0; i < V-2; i++)
387
//            prufer[i] = StdRandom.uniform(V);
388
//
389
//        // degree of vertex v = 1 + number of times it appers in Prufer sequence
390
//        int[] degree = new int[V];
391
//        for (int v = 0; v < V; v++)
392
//            degree[v] = 1;
393
//        for (int i = 0; i < V-2; i++)
394
//            degree[prufer[i]]++;
395
//
396
//        // pq contains all vertices of degree 1
397
//        MinPQ<Integer> pq = new MinPQ<Integer>();
398
//        for (int v = 0; v < V; v++)
399
//            if (degree[v] == 1) pq.insert(v);
400
//
401
//        // repeatedly delMin() degree 1 vertex that has the minimum index
402
//        for (int i = 0; i < V-2; i++) {
403
//            int v = pq.delMin();
404
//            G.addEdge(v, prufer[i]);
405
//            degree[v]--;
406
//            degree[prufer[i]]--;
407
//            if (degree[prufer[i]] == 1) pq.insert(prufer[i]);
408
//        }
409
//        G.addEdge(pq.delMin(), pq.delMin());
410
//        return G;
411
//    }
412
//
413
//    /**
414
//     * Unit tests the {@code GraphGenerator} library.
415
//     *
416
//     * @param args the command-line arguments
417
//     */
418
//    public static void main(String[] args) {
419
//        int V = Integer.parseInt(args[0]);
420
//        int E = Integer.parseInt(args[1]);
421
//        int V1 = V/2;
422
//        int V2 = V - V1;
423
//
424
//        StdOut.println("complete graph");
425
//        StdOut.println(complete(V));
426
//        StdOut.println();
427
//
428
//        StdOut.println("simple");
429
//        StdOut.println(simple(V, E));
430
//        StdOut.println();
431
//
432
//        StdOut.println("Erdos-Renyi");
433
//        double p = (double) E / (V*(V-1)/2.0);
434
//        StdOut.println(simple(V, p));
435
//        StdOut.println();
436
//
437
//        StdOut.println("complete bipartite");
438
//        StdOut.println(completeBipartite(V1, V2));
439
//        StdOut.println();
440
//
441
//        StdOut.println("bipartite");
442
//        StdOut.println(bipartite(V1, V2, E));
443
//        StdOut.println();
444
//
445
//        StdOut.println("Erdos Renyi bipartite");
446
//        double q = (double) E / (V1*V2);
447
//        StdOut.println(bipartite(V1, V2, q));
448
//        StdOut.println();
449
//
450
//        StdOut.println("path");
451
//        StdOut.println(path(V));
452
//        StdOut.println();
453
//
454
//        StdOut.println("cycle");
455
//        StdOut.println(cycle(V));
456
//        StdOut.println();
457
//
458
//        StdOut.println("binary tree");
459
//        StdOut.println(binaryTree(V));
460
//        StdOut.println();
461
//
462
//        StdOut.println("tree");
463
//        StdOut.println(tree(V));
464
//        StdOut.println();
465
//
466
//        StdOut.println("4-regular");
467
//        StdOut.println(regular(V, 4));
468
//        StdOut.println();
469
//
470
//        StdOut.println("star");
471
//        StdOut.println(star(V));
472
//        StdOut.println();
473
//
474
//        StdOut.println("wheel");
475
//        StdOut.println(wheel(V));
476
//        StdOut.println();
477
//    }
478
479
}
480