package com.ldbc.driver.generator; import com.google.common.collect.Lists; import com.ldbc.driver.util.Tuple2; import org.apache.commons.math3.random.RandomDataGenerator; import java.util.List; import static java.lang.String.format; public class DiscreteGenerator<GENERATE_TYPE> extends Generator<GENERATE_TYPE> { private final Tuple2<Double,GENERATE_TYPE>[] itemProbabilities; private final double probabilitiesSum; private final RandomDataGenerator random; DiscreteGenerator( RandomDataGenerator random, Iterable<Tuple2<Double,GENERATE_TYPE>> itemProbabilities ) { if ( false == itemProbabilities.iterator().hasNext() ) { throw new GeneratorException( "DiscreteMultiGenerator cannot be empty" ); } this.random = random; List<Tuple2<Double,GENERATE_TYPE>> itemProbabilitiesList = Lists.newArrayList( itemProbabilities ); this.itemProbabilities = itemProbabilitiesList.toArray( new Tuple2[itemProbabilitiesList.size()] ); double sum = 0; for ( int i = 0; i < this.itemProbabilities.length; i++ ) { sum += this.itemProbabilities[i]._1(); } probabilitiesSum = sum; } @Override protected GENERATE_TYPE doNext() { double randomValue = random.nextUniform( 0, 1 ); for ( int i = 0; i < itemProbabilities.length; i++ ) { Tuple2<Double,GENERATE_TYPE> item = itemProbabilities[i]; if ( randomValue < (item._1() / probabilitiesSum) ) { return item._2(); } randomValue = randomValue - (item._1() / probabilitiesSum); } String errMsg = format( "randomValue=%s\nprobabilitiesSum=%s\nitems=%s\n", randomValue, probabilitiesSum, itemProbabilities.toString() ); throw new GeneratorException( format( "Unexpected Error - failed to select next discrete element - should never get to this line\n%s", errMsg ) ); } @Override public String toString() { return "DiscreteGenerator [items=" + itemProbabilities.toString() + "]"; } }