package edu.usc.enl.dynamicmeasurement.util; import java.util.Arrays; import java.util.List; import java.util.Random; /** * Created with IntelliJ IDEA. * User: Masoud * Date: 10/8/12 * Time: 5:44 AM <br/> * A random item selector based on the passed probabilities. * The items can be numbers or any object. * Use the static randomSelect method for the simplest usage */ public class StaggerGenerator<T> { /** * commulative probabilities */ private double[] cumulative; private List<T> values; private Random random; /** * @param random * @param probabilities probability of each item * @param values values for each choice. It must be the same size as probabilities */ public StaggerGenerator(Random random, double[] probabilities, List<T> values) { this.random = random; cumulative = new double[probabilities.length]; for (int i = 0, probabilitiesLength = probabilities.length; i < probabilitiesLength; i++) { double probability = probabilities[i]; cumulative[i] = probabilities[i] + (i == 0 ? 0 : cumulative[i - 1]); } this.values = values; } public static int randomSelect(double[] cumulativeScores, Random random) { double randomValue = random.nextDouble() * cumulativeScores[cumulativeScores.length - 1]; int i = Arrays.binarySearch(cumulativeScores, randomValue); if (randomValue == 0 && i >= 0) {//there is a zero in the list and we matched on it! //go forward for (; i < cumulativeScores.length; i++) { if (cumulativeScores[i] != 0) { break; } } } else { if (i < 0) { i = -i - 1; } else { //we need the earliest of equal items for (; i > 0; i--) { if (cumulativeScores[i] != cumulativeScores[i - 1]) { break; } } } } return i; } /** * @return the next random choice based on the initializing probabilities */ public T next() { return values.get(randomSelect(cumulative, random)); } }