package vroom.common.utilities.ssj;
import java.util.HashMap;
import java.util.Map;
import umontreal.iro.lecuyer.probdist.DiscreteDistributionInt;
import umontreal.iro.lecuyer.probdist.Distribution;
import umontreal.iro.lecuyer.randvar.RandomVariateGen;
import umontreal.iro.lecuyer.randvar.RandomVariateGenInt;
import umontreal.iro.lecuyer.rng.RandomStream;
/**
* <code>RandomVariateManager</code> is a utility class that contains a mapping between {@linkplain Distribution
* distributions} and {@linkplain RandomVariateGen random number generator}.
* <p>
* For type safety this class only handles 1-dimension distributions and associated generators.
* <p>
* Creation date: Apr 23, 2010 - 9:07:36 AM
*
* @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los Andes</a>-<a
* href="http://copa.uniandes.edu.co">Copa</a> <a href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a
* href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a>
* @version 1.0
*/
public class RandomGeneratorManager {
/** Mapping between distributions and random number generators */
private final Map<Distribution, RandomVariateGen> mRandomGeneratorsMap;
/** The random stream that will be shared between all {@linkplain RandomVariateGen random generators} **/
private RandomStream mRandomStream;
/**
* Getter for randomStream
*
* @return The random stream that will be shared between all {@linkplain RandomVariateGen random generators}
*/
public RandomStream getRandomStream() {
return mRandomStream;
}
/**
* Setter for the random stream that will be shared between all {@linkplain RandomVariateGen random generators}
*
* @param randomStream
* the value to be set for randomStream
* @throws IllegalStateException
* if the random stream was already defined
*/
public void setRandomStream(RandomStream randomStream) {
if (mRandomStream != null && mRandomStream != randomStream) {
throw new IllegalStateException("The random stream for this manager has already been set: " + mRandomStream);
}
mRandomStream = randomStream;
}
/**
* Getter for the random number generator associated with a distribution.
* <p/>
* If a random number generator is already associated with <code>dist</code> then it will be returned, otherwise a
* generic number generator will be created, registered and returned.
* <p/>
* Note that a random stream has to be defined first
*
* @param dist
* the distribution for which a random number generator is needed
* @return the {@link RandomVariateGen} associated with the given distribution
* @throws IllegalStateException
* if no random stream was defined
* @see RandomVariateGen#RandomVariateGen(RandomStream, Distribution)
* @see #setRandomStream(RandomStream)
*/
public RandomVariateGen getRandomVariateGen(Distribution dist) {
RandomVariateGen gen;
if (!mRandomGeneratorsMap.containsKey(dist)) {
if (mRandomStream == null) {
throw new IllegalStateException("No random stream was defined for this instance");
}
gen = new RandomVariateGen(mRandomStream, dist);
mRandomGeneratorsMap.put(dist, gen);
} else {
gen = mRandomGeneratorsMap.get(dist);
}
return gen;
}
/**
* Getter for the random number generator associated with a distribution.
* <p/>
* If a random number generator is already associated with <code>dist</code> then it will be returned, otherwise a
* generic number generator will be created, registered and returned.
* <p/>
* Note that a random stream has to be defined first
*
* @param dist
* the distribution for which a random number generator is needed
* @return the {@link RandomVariateGen} associated with the given distribution
* @throws IllegalStateException
* if no random stream was defined
* @see RandomVariateGen#RandomVariateGen(RandomStream, Distribution)
* @see #setRandomStream(RandomStream)
*/
public RandomVariateGenInt getRandomVariateGenInt(DiscreteDistributionInt dist) {
RandomVariateGenInt gen;
if (!mRandomGeneratorsMap.containsKey(dist)) {
if (mRandomStream == null) {
throw new IllegalStateException("No random stream was defined for this instance");
}
gen = new RandomVariateGenInt(mRandomStream, dist);
mRandomGeneratorsMap.put(dist, gen);
} else {
gen = (RandomVariateGenInt) mRandomGeneratorsMap.get(dist);
}
return gen;
}
/**
* Random number generation from a distribution
*
* @param dist
* the distribution to be sampled
* @return a random number generated from the given distribution
* @see #getRandomVariateGen(Distribution)
* @see RandomVariateGen#nextDouble()
*/
public double nextDouble(Distribution dist) {
return getRandomVariateGen(dist).nextDouble();
}
/**
* Random number generation from a distribution
*
* @param dist
* the distribution to be sampled
* @return a random number generated from the given distribution
* @see #getRandomVariateGenInt(DiscreteDistributionInt)
* @see RandomVariateGenInt#nextInt()
*/
public int nextInt(DiscreteDistributionInt dist) {
return getRandomVariateGenInt(dist).nextInt();
}
/**
* Creates a new <code>RandomVariateManager</code>
*
* @param randomStream
*/
public RandomGeneratorManager() {
mRandomGeneratorsMap = new HashMap<Distribution, RandomVariateGen>();
}
/**
* Creates a new <code>RandomGeneratorManager</code>
*
* @param randomStream
* the {@link RandomStream} that will be used in the random generators.
*/
public RandomGeneratorManager(RandomStream randomStream) {
this();
mRandomStream = randomStream;
}
}