commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Andy Turner <A.G.D.Tur...@leeds.ac.uk>
Subject RE: [math] Re: binomial random generator
Date Sun, 23 Oct 2011 07:47:38 GMT
Hi,

Ahmed, I may be doing something similar. I have simulation models driven by probabilities
(values between 0 and 1). In this range I used fixed decimal precision probabilities by using
BigDecimal. I have written code that does a pseudo random test of a specific value in the
range to return true or false. I beleive this is without bias. For example for a test value
of 0.75, 25% of the time it is likely to return true. I've copied the test code for this below.
It is part of the generic package I have developed which I release via the following URL:
http://www.geog.leeds.ac.uk/people/a.turner/src/andyt/java/generic/
(If you go to get the code, please get it from the subversion repository as the bundled release
is out of date.)

I have another method that returns a pseudo random BigDecimal at a given decimal place precision
within a specified range. This might also be useful to you if you really need to have the
value rather than perform a test.

A while ago I offered my code to math (because it does BigDecimal exponentiation). I took
some steps towards fullfilling the requirements for its inclusion, but because of other demands
on my time, I have not managed to complete this which I am still keen to do this...

I hope this helps. Please let me know if it does. It may be that you are doing something more
complicated and this would need adapting to work with non uniform distributions you are using.

Best wishes,

Andy

Here are the two methods I use for the random test, the private one is for internal working:

/**
     * Effectively this is the same as generating a random number between 0 and
     * 1 and comparing it with probability and if it were higher then return
     * false and otherwise return true
     * @param a_Random
     * @param probability 0 <= probability <=1
     * @return true or false based on a random uniform test of probability
     */
    public static boolean randomUniformTest(
            Random a_Random,
            BigDecimal probability,
            int decimalPlaces,
            RoundingMode a_RoundingMode) {
        // Special case probability <= 0
        if (probability.compareTo(BigDecimal.ZERO) != 1) {
            if (probability.compareTo(BigDecimal.ZERO) == 0) {
                return false;
            } else {
                System.out.println(
                        "Warning probabilty negative in "
                        + Generic_BigDecimal.class
                        + ".randomUniformTest(Random,BigDecimal). "
                        + "Returning false.");
                return false;
            }
        }
        // Special case probability >= 1
        if (probability.compareTo(BigDecimal.ONE) != -1) {
            if (probability.compareTo(BigDecimal.ONE) == 0) {
                return true;
            } else {
                System.out.println(
                        "Warning probabilty greater > 1 in "
                        + Generic_BigDecimal.class
                        + ".randomUniformTest(Random,BigDecimal). "
                        + "Returning true.");
                return true;
            }
        }
        // Set decimalPlace precision to maximum of decimalPlaces and
        // probability.scale();
        int probabilityScale = probability.scale();
        if (decimalPlaces < probabilityScale) {
            System.out.println(
                    "Input decimalPlaces < probabilty.scale() in "
                    + Generic_BigDecimal.class
                    + ".randomUniformTest(Random,BigDecimal). "
                    + "Set decimalPlaces = probabilty.scale().");
            decimalPlaces = probabilityScale;
        }
        BigDecimal midTestValue = new BigDecimal("0.5");
        BigDecimal half_BigDecimal = new BigDecimal("0.5");
        BigDecimal two_BigDecimal = new BigDecimal("2.0");
        if (probability.compareTo(midTestValue) == 0) {
            return a_Random.nextBoolean();
        }
        if (probability.compareTo(midTestValue) == -1) {
            return randomTest(
                    a_Random,
                    probability,
                    BigDecimal.ZERO,
                    BigDecimal.ONE,
                    midTestValue,
                    half_BigDecimal,
                    two_BigDecimal,
                    decimalPlaces,
                    a_RoundingMode);
        } else {
            return !randomTest(
                    a_Random,
                    BigDecimal.ONE.subtract(probability),
                    BigDecimal.ZERO,
                    BigDecimal.ONE,
                    midTestValue,
                    half_BigDecimal,
                    two_BigDecimal,
                    decimalPlaces,
                    a_RoundingMode);
        }
    }
    private static boolean randomTest(
            Random a_Random,
            BigDecimal probability,
            BigDecimal minTestValue,
            BigDecimal maxTestValue,
            BigDecimal midTestValue,
            BigDecimal half_BigDecimal,
            BigDecimal two_BigDecimal,
            int decimalPlaces,
            RoundingMode a_RoundingMode) {
        if (probability.compareTo(midTestValue) == 0) {
            return a_Random.nextBoolean();
        }
        boolean above = a_Random.nextBoolean();
        if (above) {
            if (probability.compareTo(midTestValue) == 1) {
                // Test
                BigDecimal newMinTestValue = midTestValue;
                BigDecimal newMidTestValue = divide(
                        newMinTestValue.add(maxTestValue),
                        two_BigDecimal,
                        decimalPlaces,
                        a_RoundingMode);
                return randomTest(
                        a_Random,
                        probability,
                        newMinTestValue,
                        maxTestValue,
                        newMidTestValue,
                        half_BigDecimal,
                        two_BigDecimal,
                        decimalPlaces,
                        a_RoundingMode);
            } else {
                return false;
            }
        } else {
            if (probability.compareTo(midTestValue) == 1) {
                return true;
            } else {
                //Test
                BigDecimal newMaxTestValue = midTestValue;
                BigDecimal newMidTestValue = divide(
                        newMaxTestValue.add(minTestValue),
                        two_BigDecimal,
                        decimalPlaces,
                        a_RoundingMode);
                return randomTest(
                        a_Random,
                        probability,
                        minTestValue,
                        newMaxTestValue,
                        newMidTestValue,
                        half_BigDecimal,
                        two_BigDecimal,
                        decimalPlaces,
                        a_RoundingMode);
            }
        }
    }

________________________________________
From: Ahmed Abdeen Hamed [ahmed.elmasri@gmail.com]
Sent: 23 October 2011 04:40
To: Commons Users List
Subject: Re: [math] Re: binomial random generator

Hi Phil,

Thanks very much for your quick response. I am doing some simulations that
produce probailities which are in turn must be compared to certains rates.
Here is an example of what I am doing:

  if (randBinomial.nextBinomial(1, Simulation.MRATE)==1) {

// the condition can be replaced by the following uncommented condition

//randM.nextDouble() < Simulation.M_RATE;

  if (gt[i] == 0) {

   gt[i] = 1;

  } else {

   gt[i] = 0;

  }

  }

Please let me know if I am using Binomial object and its method correctly.

Thanks again!

Ahmed


On Sat, Oct 22, 2011 at 11:29 PM, Phil Steitz <phil.steitz@gmail.com> wrote:

> On 10/22/11 8:15 PM, Ahmed Abdeen Hamed wrote:
> > Hello friends,
> >
> > I am using the following code in a program I am writing:
> >     private static JDKRandomGenerator rg = new JDKRandomGenerator();
> >     private static RandomDataImpl randBinomial = new RandomDataImpl(rg);
> >
> > However, it is slowing down things very much. When I replace generator
> with
> > a java.util.Random object it works fine without the performance issues.
> Is
> > that expected with this library? Is there any work around? My programs
> are
> > very time consuming and I have been repeatedly running them. I really
> need
> > some tips if there is anything I can do to enhance the performance.
>
> That depends on how you are using randBinomial above.  Can you share
> the code that uses randBinomial and what you mean by "replace
> generator with a java.util.Random object?"  It will also help to
> describe what exactly you are trying to accomplish with the code.
>
> Phil
> >
> > Thanks very much!
> > Ahmed
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
> For additional commands, e-mail: user-help@commons.apache.org
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@commons.apache.org
For additional commands, e-mail: user-help@commons.apache.org


Mime
View raw message