/*
* Copyright (c) 2003, the JUNG Project and the Regents of the University
* of California
* All rights reserved.
*
* This software is open-source under the BSD license; see either
* "license.txt" or
* http://jung.sourceforge.net/license.txt for a description.
*/
package edu.uci.ics.jung.algorithms.generators.random;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.apache.commons.collections15.Factory;
import edu.uci.ics.jung.algorithms.generators.GraphGenerator;
import edu.uci.ics.jung.graph.Graph;
/**
* Graph generator that generates undirected graphs with power-law degree distributions.
* @author Scott White
* @see "A Steady State Model for Graph Power Law by David Eppstein and Joseph Wang"
*/
public class EppsteinPowerLawGenerator<V,E> implements GraphGenerator<V,E> {
private int mNumVertices;
private int mNumEdges;
private int mNumIterations;
private double mMaxDegree;
private Random mRandom;
private Factory<Graph<V,E>> graphFactory;
private Factory<V> vertexFactory;
private Factory<E> edgeFactory;
/**
* Creates an instance with the specified factories and specifications.
* @param graphFactory the factory to use to generate the graph
* @param vertexFactory the factory to use to create vertices
* @param edgeFactory the factory to use to create edges
* @param numVertices the number of vertices for the generated graph
* @param numEdges the number of edges the generated graph will have, should be Theta(numVertices)
* @param r the number of iterations to use; the larger the value the better the graph's degree
* distribution will approximate a power-law
*/
public EppsteinPowerLawGenerator(Factory<Graph<V,E>> graphFactory,
Factory<V> vertexFactory, Factory<E> edgeFactory,
int numVertices, int numEdges, int r) {
this.graphFactory = graphFactory;
this.vertexFactory = vertexFactory;
this.edgeFactory = edgeFactory;
mNumVertices = numVertices;
mNumEdges = numEdges;
mNumIterations = r;
mRandom = new Random();
}
protected Graph<V,E> initializeGraph() {
Graph<V,E> graph = null;
graph = graphFactory.create();
for(int i=0; i<mNumVertices; i++) {
graph.addVertex(vertexFactory.create());
}
List<V> vertices = new ArrayList<V>(graph.getVertices());
while (graph.getEdgeCount() < mNumEdges) {
V u = vertices.get((int) (mRandom.nextDouble() * mNumVertices));
V v = vertices.get((int) (mRandom.nextDouble() * mNumVertices));
if (!graph.isSuccessor(v,u)) {
graph.addEdge(edgeFactory.create(), u, v);
}
}
double maxDegree = 0;
for (V v : graph.getVertices()) {
maxDegree = Math.max(graph.degree(v),maxDegree);
}
mMaxDegree = maxDegree; //(maxDegree+1)*(maxDegree)/2;
return graph;
}
/**
* Generates a graph whose degree distribution approximates a power-law.
* @return the generated graph
*/
public Graph<V,E> create() {
Graph<V,E> graph = initializeGraph();
List<V> vertices = new ArrayList<V>(graph.getVertices());
for (int rIdx = 0; rIdx < mNumIterations; rIdx++) {
V v = null;
int degree = 0;
do {
v = vertices.get((int) (mRandom.nextDouble() * mNumVertices));
degree = graph.degree(v);
} while (degree == 0);
List<E> edges = new ArrayList<E>(graph.getIncidentEdges(v));
E randomExistingEdge = edges.get((int) (mRandom.nextDouble()*degree));
// FIXME: look at email thread on a more efficient RNG for arbitrary distributions
V x = vertices.get((int) (mRandom.nextDouble() * mNumVertices));
V y = null;
do {
y = vertices.get((int) (mRandom.nextDouble() * mNumVertices));
} while (mRandom.nextDouble() > ((graph.degree(y)+1)/mMaxDegree));
if (!graph.isSuccessor(y,x) && x != y) {
graph.removeEdge(randomExistingEdge);
graph.addEdge(edgeFactory.create(), x, y);
}
}
return graph;
}
/**
* Sets the seed for the random number generator.
* @param seed input to the random number generator.
*/
public void setSeed(long seed) {
mRandom.setSeed(seed);
}
}
|