/* * 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 */ @Override 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); } }