com.phoenixst.plexus.examples.RandomGraphFactory.java Source code

Java tutorial

Introduction

Here is the source code for com.phoenixst.plexus.examples.RandomGraphFactory.java

Source

/*
 *  $Id: RandomGraphFactory.java,v 1.9 2005/10/03 15:14:43 rconner Exp $
 *
 *  Copyright (C) 1994-2005 by Phoenix Software Technologists,
 *  Inc. and others.  All rights reserved.
 *
 *  THIS PROGRAM AND DOCUMENTATION IS PROVIDED UNDER THE TERMS OF THE
 *  COMMON PUBLIC LICENSE ("AGREEMENT") WHICH ACCOMPANIES IT.  ANY
 *  USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES
 *  RECIPIENT'S ACCEPTANCE OF THE AGREEMENT.
 *
 *  The license text can also be found at
 *    http://opensource.org/licenses/cpl.php
 */

package com.phoenixst.plexus.examples;

import java.util.Random;

import org.apache.commons.collections.Predicate;

import com.phoenixst.plexus.*;

/**
 *  This class contains static factory methods for creating random
 *  graphs.
 *
 *  @version    $Revision: 1.9 $
 *  @author     Ray A. Conner
 *
 *  @since      1.0
 */
public class RandomGraphFactory {

    ////////////////////////////////////////
    // Constructor
    ////////////////////////////////////////

    /**
     *  Prevent instantiation.
     */
    private RandomGraphFactory() {
        super();
    }

    ////////////////////////////////////////
    // Factory Methods
    ////////////////////////////////////////

    /**
     *  Creates a random graph with <code>n</code> nodes where each
     *  pair of nodes has probability <code>prob</code> of having an
     *  edge between them.
     */
    public static Graph createStandardGraph(int n, double prob) {
        if (prob < 0.0 || prob > 1.0) {
            throw new IllegalArgumentException("Probability must be between 0.0 and 1.0, inclusive.");
        }
        Graph graph = new DefaultGraph(new EmptyGraph(n));
        for (int head = 1; head < n; head++) {
            Object headNode = new Integer(head);
            for (int tail = 0; tail < head; tail++) {
                if (Math.random() < prob) {
                    graph.addEdge(null, new Integer(tail), headNode, true);
                }
            }
        }
        return graph;
    }

    /**
     *  Creates a random graph according to the Watts-Strogatz model.
     *  The number <code>d</code> here is half of <code>K</code> in
     *  the standard literature.
     *
     *  <P>Start with a circulant graph.  Arrange the nodes in a
     *  circle, starting at 0 and increasing, in order, clockwise.
     *  Begin with node 0 and the edge which connects it to its
     *  nearest clockwise neighbor, which is node 1.  With probability
     *  <code>prob</code>, reconnect this edge from node 0 to a
     *  uniformly randomly selected node, with duplicate and self edges
     *  forbidden.  Repeat this process for each node, moving
     *  clockwise around the circle.  Now, repeat the entire cycle,
     *  but instead choose edges which connect nodes to their
     *  second-nearest clockwise neighbor.  And so on, until every one
     *  of the original edges has been considered.
     */
    public static Graph createWattsStrogatz(int n, int d, double prob) {
        if (prob < 0.0 || prob > 1.0) {
            throw new IllegalArgumentException("Probability must be between 0.0 and 1.0, inclusive.");
        }
        Graph graph = new DefaultGraph(new CirculantGraph(n, d));
        Random random = new Random();
        for (int dist = 1; dist <= d; dist++) {
            for (int nodeIndex = 0; nodeIndex < n; nodeIndex++) {
                if (random.nextDouble() < prob) {
                    Object tail = new Integer(nodeIndex);
                    Object head = new Integer((nodeIndex + dist) % n);
                    Predicate edgePred = EdgePredicateFactory.createEqualsNodes(tail, head,
                            GraphUtils.ANY_DIRECTION_MASK);
                    graph.removeEdge(graph.getEdge(edgePred));
                    while (true) {
                        head = new Integer(random.nextInt(n));
                        Predicate traverserPred = TraverserPredicateFactory.createEqualsNode(head,
                                GraphUtils.ANY_DIRECTION_MASK);
                        if (!tail.equals(head) && graph.getIncidentEdge(tail, traverserPred) == null) {
                            graph.addEdge(null, tail, head, true);
                            break;
                        }
                    }
                }
            }
        }
        return graph;
    }

    /**
     *  Creates a random graph according to the Barabasi-Albert model.
     *
     *  <P>Start with <code>numInitialNodes</code> nodes.  At each
     *  step, add a new node which is connected to
     *  <code>numEdges</code> existing nodes, with preference given to
     *  nodes that are more highly connected.
     */
    public static Graph createBarabasiAlbert(int numInitialNodes, int numFinalNodes, int numEdges) {
        if (numEdges > numInitialNodes) {
            throw new IllegalArgumentException("Number of edges cannot be more than the number of initial nodes.");
        }
        Graph graph = new DefaultGraph(new EmptyGraph(numInitialNodes + 1));
        Random random = new Random();

        // Start out with numEdges randomly connected from the last
        // node to other nodes.
        Object tail = new Integer(numInitialNodes);
        for (int k = 0; k < numEdges; k++) {
            while (true) {
                Object head = new Integer(random.nextInt(numInitialNodes));
                Predicate traverserPred = TraverserPredicateFactory.createEqualsNode(head,
                        GraphUtils.ANY_DIRECTION_MASK);
                if (graph.getIncidentEdge(tail, traverserPred) == null) {
                    graph.addEdge(null, tail, head, true);
                    break;
                }
            }
        }

        // Now, do the rest of the work
        int totalDegree = numEdges * 2;
        for (int i = numInitialNodes + 1; i < numFinalNodes; i++, totalDegree += numEdges * 2) {
            tail = new Integer(i);
            graph.addNode(tail);
            for (int k = 0; k < numEdges; k++) {
                while (true) {
                    int randomDegreeSum = random.nextInt(totalDegree);
                    Object head = new Integer(0);
                    int degreeSum = 0;
                    for (int headIndex = 0; degreeSum < randomDegreeSum; headIndex++) {
                        head = new Integer(headIndex);
                        degreeSum += graph.degree(head);
                    }
                    Predicate traverserPred = TraverserPredicateFactory.createEqualsNode(head,
                            GraphUtils.ANY_DIRECTION_MASK);
                    if (graph.getIncidentEdge(tail, traverserPred) == null) {
                        graph.addEdge(null, tail, head, true);
                        break;
                    }
                }
            }
        }
        return graph;
    }

}