I'm afraid I'm not a professional Java programmer, nor a mathematician,
but I'd like to be able to generate a set of integers with a Poisson
distribution around a starting value (lambda). The application for which
I wish to do this is deriving confidence limits for analysis of radio
meteor observations.
<http://www.radiometeor.plus.com/>
The method I'm using, derived from "Simulation and the Monte Carlo
Method", by Rubinstein and Kroese works well for small starting values.
But, as the text of this book the algorithm becomes slow for large
starting values of lambda. In my case, the algorithm becomes
impractically slow as Lambda increases above about 745. Some radio
meteor observers have hour counts which exceed this value.
Does anyone have code to implement any alternative method to derive a
Poisson random variable?
Many thanks.
/*
* TestPoissonDistribution.java
* A method to test the Poisson distribution generator.
*/
import java.util.Random;
public class TestPoissonDistribution
{
public static void main(String[] args)
{
for(int i = 0; i <= 600; i++)
{
System.out.println();
for(int j = 0; j <= 10; j++)
{
System.out.print(distribute(i) + ", ");
}
}
}
/**
* A method to randomize a value based on a Poisson distribution.
* @param lambda The starting value.
* @return The integer which forms part of the distribution
* See pp 65 of Simulation and the Monte Carlo Method by
* Rubinstein and Kroese
*/
public static int distribute(int lambda)
{
int n = 1;
double a = 1.0;
Random r = new Random();
while(true)
{
a *= r.nextDouble();
if(a < Math.exp((double)-lambda)) break;
n += 1;
}
return n - 1;
}
}
--
David Entwistle
The Colt library includes Poisson distribution support. See
http://acs.lbl.gov/~hoschek/colt/api/cern/jet/random/Poisson.html
I have not benchmarked it, so I am merely bringing it to your attention
as an alternative to consider.
Patricia
Patricia,
Thanks very much for bring the Colt library to my attention - it
certainly looks to do what I want. I'll give it a go.
Thanks again and best wishes for the season,
--
David Entwistle
David Entwistle wrote:
> public static int distribute(int lambda)
Consider making this an instance variable.
> {
> int n = 1;
> double a = 1.0;
> Random r = new Random();
This will restart the pseudorandom sequence every time the method is called.
Make the Random variable an instance variable instead.
> while(true)
> {
> a *= r.nextDouble();
> if(a < Math.exp((double)-lambda)) break;
> n += 1;
> }
> return n - 1;
> }
> }
--
Lew
There are two ways this sort of random number generator can be used:
1. Get a lot of samples from the same distribution. For this, the best
design is to have lambda be an instance variable, use a parameterless
instance method to return the sampled value, and create an instance for
each different value of lambda.
2. Get samples from a lot of different distributions. A static method
with lambda as parameter is better for this. In the calling code it
replaces:
int sample = new Poisson(myLambda).sample();
with the simpler code:
int sample = Poisson.sample(myLambda);
The Colt Poisson class is designed to support both use cases, and so has
both a constructor for an object with lambda bound to a specific value
and a static method.
David will presumably know how his program uses this, and should pick
whichever design fits better.
Patricia
Lew wrote:
> Consider making this an instance variable.
I meant instance method - oops.
--
Lew
Lew wrote:
>> Consider making this an instance variable [sic].
Patricia Shanahan wrote:
> There are two ways this sort of random number generator can be used:
>
> 1. Get a lot of samples from the same distribution. For this, the best
> design is to have lambda be an instance variable, use a parameterless
> instance method to return the sampled value, and create an instance for
> each different value of lambda.
>
> 2. Get samples from a lot of different distributions. A static method
> with lambda as parameter is better for this. In the calling code it
> replaces:
>
> int sample = new Poisson(myLambda).sample();
>
> with the simpler code:
>
> int sample = Poisson.sample(myLambda);
>
> The Colt Poisson class is designed to support both use cases, and so has
> both a constructor for an object with lambda bound to a specific value
> and a static method.
>
> David will presumably know how his program uses this, and should pick
> whichever design fits better.
That is a good explication of what to consider when considering whether to
make something an instance member. I would add that an instance method is
also useful with a parameter if one wants not to repeat the pseudorandom
sequence of the underlying 'Random' variable. One instantiates a 'Poisson'
and repeatedly calls 'sample( lambda )' on it, thus avoiding repetition of
"random" values for successive calls.
Sometimes an object has state that is not explicitly visible to its consumers.
Static variables for such state are an antipattern, particularly harmful in
concurrent applications, so it would be best to instantiate an object even
with the method that takes a parameter.
--
Lew
A side note. For this type of work, I strongly recommend the following:
1. Design the program so that you can force a seed value for each
sequence of random numbers in the program. (Usually, there should only
be one sequence.)
2. Report the actual seed in the program output.
It can be *very* frustrating if you get an anomalous result and want to
investigate, but cannot reproduce the problem.
Patricia
> Random r = new Random();
This should be done only once, not once per generation. Put the code
into static init. Otherwise you will keep getting the same numbers
since the same time will be used as a seed.
--
Roedy Green Canadian Mind Products
http://mindprod.com
PM Steven Harper is fixated on the costs of implementing Kyoto, estimated as high as 1% of GDP.
However, he refuses to consider the costs of not implementing Kyoto which the
famous economist Nicholas Stern estimated at 5 to 20% of GDP