Search code examples
javarandomthread-safetyapache-commons-math

Changing distribution parameters during program flow in Apache Commons Math


I need to generate random numbers in my code but I want to change the parameters of the Distribution based on the current scenario. The application can run as single or multi-threaded application.

My question is that, should I initialize the RandomGenerator object in the constructor of my class and then use that RandomGenerator object to (re-)initialize the NormalDistribution, BetaDistribution or any other object of AbstractRealDistribution repeatedly, or just initialize my distribution object after I need to update the parameters.

Which is is a better option in terms of generating good random numbers and also in terms of optimality?

Case 1:

class Test {
    protected RandomGenerator rng;
    public Test() {
        rng = new Well19937c();
    }
    private void someFunction(double mean, doube std_dev) {
        NormalDistribution norm = new NormalDistribution(this.rng, mean, std_dev);
        while (condition is met) {
            // do some calculation, create some random numbers, get new mean and std_dev
            norm = new NormalDistribution(this.rng, new_mean, new_std_dev);
        }
    }
}

Case 2:

class Test {
    private void someFunction(double mean, doube std_dev) {
        NormalDistribution norm = new NormalDistribution(mean, std_dev);
        while (condition is met) {
            // do some calculation, create some random numbers, get new mean and std_dev
            norm = new NormalDistribution(new_mean, new_std_dev);
        }
    }
}

Solution

  • You should reuse the RandomGenerator across calls. The simplest way to generate random values with different distribution parameters is to use the RandomDataGenerator class in the random package:

    RandomDataGenerator generator = new RandomDataGenerator(new Well19937c());
    // Unit normal
    double normDev = generator.nextGaussian(0, 1);
    // mean = 0.5, std dev = 2
    double normDev2 = generator.nextGaussian(0.5, 2);
    // exponential, mean = 1
    double expDev = generator.nextExponential(1);