Presume I have the following case:
- int value
a - int value
b, for whicha < b - int value i, for which
a <= i < b - I need an int value
x, for whicha <= x < b, randomly chosen, according to a non-uniform distribution: the distribution should follow a bell curve which is centered aroundi.
In Java, I have the following methods available on java.util.Random:
nextInt(int m): int between0andmnextDouble(): double between0.0and1.0nextGaussian(): double between-Infinityand+Infinity, usually close to0.0.
How do I build such a non-uniform distribution from these building blocks? How do I reliably and efficiently transform nextGaussian() into nextGaussian(a, b, i)? The part I am struggling with is to enforce that x is selected between a and b (without doing a trial-and-error).
Asked By : Geoffrey De Smet
Answered By : Mike Dunlavey
I would generate a beta distribution, and then expand to the desired range and round to the nearest integer.
A beta distribution on the 0-1 scale has two parameters: $Beta(a,b)$. $Beta(1,1)$ is simply a flat uniform. You want $a$ and $b$ to be > 1 or it won't have a central peak. The mean is $a/(a+b)$, and the mode (peak) is $(a-1)/(a+b-2)$.
The larger $a$ and $b$ are, the more "peaked" the distribution is.
Here's how to generate it from uniform random numbers if $a$ and $b$ are integers:
First, here's how you generate a Gamma variate $Gamma(1,a)$.
double Gamma1(int n){ double sum = 0; for (int i = 0; i < n; i++){ sum += -log(getUniform()); } return sum; } Then
double Beta(int a, int b){ double x = Gamma1(a); double y = Gamma1(b); return x/(x+y); } Then for your problem, you have a span from A to B with mode at I. Then the distance from A to I is fraction $(I-A)/(B-A)$, so that is the mode of the distribution. Then decide how large you want $a+b$ to be, the more the sharper. You might start with 10, call it $n$. Then calculate $$a = (I-A)/(B-A)*(n-2)+1$$ and use the nearest integer value for $a$, and of course $b=n-a$.
Then all you gotta do is calculate
A + (B-A)*Beta(a,b) and round to the nearest integer.
It sounds like your requirements are pretty flexible, so this should be good enough.
Anyway, look up Beta distribution.
EDIT: Another way that might be simpler: Use order statistics. Generate $n$ uniforms, sort them, and then choose the $a$th one, and scale that.
Best Answer from StackOverflow
Question Source : http://cs.stackexchange.com/questions/18467
0 comments:
Post a Comment
Let us know your responses and feedback